SQL 注入原理
SQL注入攻擊指的是通過(guò)構(gòu)建特殊的輸入作為參數(shù)傳入Web應(yīng)用程序,而這些輸入大都是SQL語(yǔ)法里的一些組合,通過(guò)執(zhí)行SQL語(yǔ)句進(jìn)而執(zhí)行攻擊者所要的操作,其主要原因是程序沒(méi)有細(xì)致地過(guò)濾用戶(hù)輸入的數(shù)據(jù),致使非法數(shù)據(jù)侵入系統(tǒng)。
SQL 注入分類(lèi)1. 數(shù)字型注入
當(dāng)輸入的參數(shù)為整型時(shí),則有可能存在數(shù)字型注入漏洞。
假設(shè)存在一條 URL 為:
可以對(duì)后臺(tái)的 SQL 語(yǔ)句猜測(cè)為:
* FROM table WHERE id=1
判斷數(shù)字型漏洞的 SQL 注入點(diǎn):
① 先在輸入框中輸入一個(gè)單引號(hào)'
這樣的 SQL 語(yǔ)句就會(huì)變?yōu)椋?/p>
* FROM table WHERE id=1',
不符合語(yǔ)法,所以該語(yǔ)句肯定會(huì)出錯(cuò),導(dǎo)致腳本程序無(wú)法從數(shù)據(jù)庫(kù)獲取數(shù)據(jù),從而使原來(lái)的頁(yè)面出現(xiàn)異常。
② 在輸入框中輸入and 1 = 1
SQL語(yǔ)句變?yōu)椋?/p>
* FROM table WHERE id=1 and 1 = 1
語(yǔ)句正確,執(zhí)行正常,返回的數(shù)據(jù)與原始請(qǐng)求無(wú)任何差異。
③ 在數(shù)據(jù)庫(kù)中輸入and 1 = 2
SQL 語(yǔ)句變?yōu)椋?/p>
* FROM table WHERE id=1 and 1 = 2
雖然語(yǔ)法正確,語(yǔ)句執(zhí)行正常,但是邏輯錯(cuò)誤,因?yàn)?1 = 2 為永假,所以返回?cái)?shù)據(jù)與原始請(qǐng)求有差異。
如果以上三個(gè)步驟全部滿(mǎn)足,則程序就可能存在數(shù)字型 SQL 注入漏洞。
2. 字符型注入
當(dāng)輸入?yún)?shù)為字符串時(shí),則可能存在字符型注入漏洞。數(shù)字型與字符型注入最大的區(qū)別在于:數(shù)字型不需要單引號(hào)閉合,而字符型一般需要使用單引號(hào)來(lái)閉合。
字符型注入最關(guān)鍵的是如何閉合 SQL 語(yǔ)句以及注釋多余的代碼。
假設(shè)后臺(tái)的 SQL 語(yǔ)句如下:
* FROM table WHERE = 'admin'
判斷字符型漏洞的 SQL 注入點(diǎn):
① 還是先輸入單引號(hào)admin'來(lái)測(cè)試
這樣的 SQL 語(yǔ)句就會(huì)變?yōu)椋?/p>
* FROM table WHERE = 'admin''。
頁(yè)面異常。
② 輸入:admin' and 1 = 1 --
注意:在 admin 后有一個(gè)單引號(hào)',用于字符串閉合,最后還有一個(gè)注釋符--(兩條杠后面還有一個(gè)空格?。?!)。
SQL 語(yǔ)句變?yōu)椋?/p>
* FROM table WHERE = 'admin' and 1 = 1 --
頁(yè)面顯示正確。
③ 輸入:admin' and 1 = 2 --
SQL 語(yǔ)句變?yōu)椋?/p>
* FROM table WHERE = 'admin' and 1 = 2 --
頁(yè)面錯(cuò)誤。
滿(mǎn)足上面三個(gè)步驟則有可能存在字符型 SQL 注入。
3. 其他類(lèi)型
其實(shí)我覺(jué)得 SQL 注入只有兩種類(lèi)型:數(shù)字型與字符型。很多人可能會(huì)說(shuō)還有如: 注入、POST 注入、延時(shí)注入等。
的確如此,但這些類(lèi)型的注入歸根結(jié)底也是數(shù)字型和字符型注入的不同展現(xiàn)形式或者注入的位置不同罷了。
以下是一些常見(jiàn)的注入叫法:
常見(jiàn)數(shù)據(jù)庫(kù)的注入
攻擊者對(duì)于數(shù)據(jù)庫(kù)注入,無(wú)非是利用數(shù)據(jù)庫(kù)獲取更多的數(shù)據(jù)或者更大的權(quán)限,利用的方式可以歸結(jié)為以下幾類(lèi):
攻擊者對(duì)于程序注入,無(wú)論任何數(shù)據(jù)庫(kù),無(wú)非都是在做這三件事sql數(shù)據(jù)庫(kù)文件類(lèi)型,只不過(guò)不同的數(shù)據(jù)庫(kù)注入的 SQL 語(yǔ)句不一樣罷了。
這里介紹三種數(shù)據(jù)庫(kù)的注入: 11g、MySQL 5.1 和 SQL 2008。
SQL . 利用錯(cuò)誤消息提取信息
SQL 數(shù)據(jù)庫(kù)是一個(gè)非常優(yōu)秀的數(shù)據(jù)庫(kù),它可以準(zhǔn)確地定位錯(cuò)誤信息,這對(duì)攻擊者來(lái)說(shuō)是一件十分美好的事情,因?yàn)楣粽呖梢酝ㄟ^(guò)錯(cuò)誤消息提取自己想要的數(shù)據(jù)。
① 枚舉當(dāng)前表或者列
假設(shè)選擇存在這樣一張表:
查詢(xún) root 用戶(hù)的詳細(xì)信息,SQL 語(yǔ)句猜測(cè)如下:
* FROM user WHERE = 'root' AND = 'root'
攻擊者可以利用 SQL 特性來(lái)獲取敏感信息,在輸入框中輸入如下語(yǔ)句:
' 1 = 1 --
最終執(zhí)行的 SQL 語(yǔ)句就會(huì)變?yōu)椋?/p>
* FROM user WHERE = 'root' AND = 'root' 1 = 1 --
那么 SQL 的執(zhí)行器可能會(huì)拋出一個(gè)錯(cuò)誤:
攻擊者就可以發(fā)現(xiàn)當(dāng)前的表名為 user、而且存在字段 id。
攻擊者可以利用此特性繼續(xù)得到其他列名,輸入如下語(yǔ)句:
' GROUP BY users.id 1 = 1 --
則 SQL 語(yǔ)句變?yōu)椋?/p>
* FROM user WHERE = 'root' AND = 'root' GROUP BY users.id 1 = 1 --
拋出錯(cuò)誤:
由此可以看到包含列名 ??梢砸淮芜f歸查詢(xún),知道沒(méi)有錯(cuò)誤消息返回位置,這樣就可以利用 字句得到當(dāng)表的所有列名。
注:指定的每一列都應(yīng)該出現(xiàn)在Group By子句中,除非對(duì)這一列使用了聚合函數(shù)
②. 利用數(shù)據(jù)類(lèi)型錯(cuò)誤提取數(shù)據(jù)
如果試圖將一個(gè)字符串與非字符串比較,或者將一個(gè)字符串轉(zhuǎn)換為另一個(gè)不兼容的類(lèi)型,那么SQL 編輯器將會(huì)拋出異常。
如下列 SQL 語(yǔ)句:
* FROM user WHERE = 'abc' AND = 'abc' AND 1 > ( TOP 1 FROM users)
執(zhí)行器錯(cuò)誤提示:
這就可以獲取到用戶(hù)的用戶(hù)名為 root。因?yàn)樵谧硬樵?xún) TOP 1 FROM users中,將查詢(xún)到的用戶(hù)名的第一個(gè)返回,返回類(lèi)型是 類(lèi)型,然后要跟 int 類(lèi)型的 1 比較,兩種類(lèi)型不同的數(shù)據(jù)無(wú)法比較而報(bào)錯(cuò),從而導(dǎo)致了數(shù)據(jù)泄露。
利用此方法可以遞歸推導(dǎo)出所有的賬戶(hù)信息:
* FROM users WHERE = 'abc' AND = 'abc' AND 1 > ( TOP 1 FROM users WHERE not in ('root'))。
通過(guò)構(gòu)造此語(yǔ)句就可以獲得下一個(gè) 用戶(hù)名;若把子查詢(xún)中的 換成其他列名,則可以獲取其他列的信息,這里就不再贅述。
2. 獲取元數(shù)據(jù)
SQL 提供了大量視圖,便于取得元數(shù)據(jù)??梢韵炔聹y(cè)出表的列數(shù),然后用 UNION 來(lái)構(gòu)造 SQL 語(yǔ)句獲取其中的數(shù)據(jù)。
如:
*** FROM *** WHERE id = *** UNION 1, FROM .
若當(dāng)前表的列數(shù)為 2,則可以 UNION 語(yǔ)句獲取當(dāng)前數(shù)據(jù)庫(kù)表。具體怎么猜測(cè)當(dāng)前表的列數(shù),后面進(jìn)行描述。
一些常用的系統(tǒng)數(shù)據(jù)庫(kù)視圖:
3. ORDER BY 子句猜測(cè)列數(shù)
可以用 ORDER BY 語(yǔ)句來(lái)判斷當(dāng)前表的列數(shù)。
如:
① * FROM users WHERE id = 1——SQL執(zhí)行正常
② * FROM users WHERE id = 1 ORDER BY 1(按照第一列排序)——SQL執(zhí)行正常
③ * FROM users WHERE id = 1 ORDER BY 2(按照第二列排序)——SQL執(zhí)行正常
④ * FROM users WHERE id = 1 ORDER BY 3(按照第三列排序)——SQL 執(zhí)行正常
⑤ * FROM users WHERE id = 1 ORDER BY 4(按照第四列排序)——SQL 拋出異常:
由此可以得出,當(dāng)前表的列數(shù)只有 3 列,因?yàn)楫?dāng)按照第 4 列排序時(shí)報(bào)錯(cuò)了。在 和 MySql 數(shù)據(jù)庫(kù)中同樣適用此方法。
在得知列數(shù)后,攻擊者通常會(huì)配合 UNION 關(guān)鍵字進(jìn)行下一步的攻擊。
4. UNION 查詢(xún)
UNION 關(guān)鍵字將兩個(gè)或多個(gè)查詢(xún)結(jié)果組合為單個(gè)結(jié)果集,大部分?jǐn)?shù)據(jù)庫(kù)都支持 UNION 查詢(xún)。但適用 UNION 合并兩個(gè)結(jié)果有如下基本規(guī)則:
① 用 UNION 查詢(xún)猜測(cè)列數(shù)
不僅可以用 ORDER BY 方法來(lái)猜測(cè)列數(shù),UNION 方法同樣可以。
在之前假設(shè)的 user 表中有 5 列,若我們用 UNION 聯(lián)合查詢(xún):
* FROM users WHERE id = 1 UNION 1
數(shù)據(jù)庫(kù)會(huì)發(fā)出異常:
可以通過(guò)遞歸查詢(xún),直到無(wú)錯(cuò)誤產(chǎn)生,就可以得知 User 表的查詢(xún)字段數(shù):
UNION 1,2、UNION 1,2,3
也可以將 后面的數(shù)字改為 null、這樣不容易出現(xiàn)不兼容的異常。
② 聯(lián)合查詢(xún)敏感信息
在得知列數(shù)為 4后,可以使用一下語(yǔ)句繼續(xù)注入:
UNION 'x', null, null, null FROM WHERE xtype='U'(注:xtype=‘U’ 表示對(duì)象類(lèi)型是表)
若第一列的數(shù)據(jù)類(lèi)型不匹配,數(shù)據(jù)庫(kù)會(huì)報(bào)錯(cuò),那么可以遞歸查詢(xún),直到語(yǔ)句兼容。等到語(yǔ)句正常執(zhí)行,就可以將 x 換為 SQL 語(yǔ)句,查詢(xún)敏感信息。
5. 利用SQL 提供的系統(tǒng)函數(shù)
SQL 提供了非常多的系統(tǒng)函數(shù),利用該系統(tǒng)函數(shù)可以訪(fǎng)問(wèn) SQL 系統(tǒng)表中的信息,而無(wú)需使用 SQL 查詢(xún)語(yǔ)句。
如:
6. 存儲(chǔ)過(guò)程
存儲(chǔ)過(guò)程 ( ) 是在大型數(shù)據(jù)庫(kù)系統(tǒng)中為了完成特定功能的一組 SQL “函數(shù)”,如:執(zhí)行系統(tǒng)命令、查看注冊(cè)表、讀取磁盤(pán)目錄等。
攻擊者最長(zhǎng)使用的存儲(chǔ)過(guò)程是“”,這個(gè)存儲(chǔ)過(guò)程允許用戶(hù)執(zhí)行操作系統(tǒng)命令。
例如:中存在注入點(diǎn),那么攻擊者就可以實(shí)施命令攻擊:
;exec 'net user test test /add'
最終執(zhí)行的 SQL 語(yǔ)句如下:
* FROM table WHERE id=1; exec 'net user test test /add'
分號(hào)后面的那一段語(yǔ)句就可以為攻擊者在對(duì)方服務(wù)器上新建一個(gè)用戶(hù)名為 test、密碼為 test 的用戶(hù)。
注:并不是任何數(shù)據(jù)庫(kù)用戶(hù)都可以使用此類(lèi)存儲(chǔ)過(guò)程,用戶(hù)必須持有 權(quán)限。
常見(jiàn)的危險(xiǎn)存儲(chǔ)過(guò)程如下表:
存儲(chǔ)過(guò)程說(shuō)明
創(chuàng)建新的 SQL 登錄,該登錄允許用戶(hù)使用 SQL 身份連接到 SQL 實(shí)例
從當(dāng)前數(shù)據(jù)庫(kù)中刪除數(shù)據(jù)庫(kù)用戶(hù)
提供 本地組列表或在指定的 域中定義全局組列表
讀取注冊(cè)表
寫(xiě)入注冊(cè)表
刪除注冊(cè)表
讀取目錄
更改密碼
停止或激活某服務(wù)
另外sql數(shù)據(jù)庫(kù)文件類(lèi)型,任何數(shù)據(jù)庫(kù)在使用一些特殊的函數(shù)或存儲(chǔ)過(guò)程時(shí),都需要特定的權(quán)限。常見(jiàn)的SQL 數(shù)據(jù)庫(kù)的角色與權(quán)限如下:
角色權(quán)限
可以運(yùn)行 BULK 語(yǔ)句
可以創(chuàng)建、更改、刪除和還原任何數(shù)據(jù)庫(kù)
可以管理磁盤(pán)文件
可以種植在數(shù)據(jù)庫(kù)引擎中運(yùn)行的實(shí)例
可以管理登錄名及其屬性;可以利用 GRANT、DENY 和 服務(wù)器級(jí)別的權(quán)限;還可以利用 GRANT、DENY 和 數(shù)據(jù)庫(kù)級(jí)別的權(quán)限;此外也可以重置 SQL 登錄名的密碼
可以更改服務(wù)器范圍的配置選項(xiàng)和關(guān)閉服務(wù)器
可以添加和刪除鏈接服務(wù)器,并可以執(zhí)行某些系統(tǒng)存儲(chǔ)過(guò)程
可以在數(shù)據(jù)庫(kù)引擎中執(zhí)行任何活動(dòng)
7. 動(dòng)態(tài)執(zhí)行
SQL 支持動(dòng)態(tài)執(zhí)行語(yǔ)句,用戶(hù)可以提交一個(gè)字符串來(lái)執(zhí)行 SQL 語(yǔ)句。
如:exec(' , FROM users')
也可以通過(guò)定義十六進(jìn)制的 SQL 語(yǔ)句,使用 exec 函數(shù)執(zhí)行。大部分 Web 應(yīng)用程序和防火墻都過(guò)濾了單引號(hào),利用 exec 執(zhí)行十六進(jìn)制 SQL 語(yǔ)句可以突破很多防火墻及防注入程序,如:
或者:
/**/@query/**/(888)/**//**/@query=/**/exec(@query)
MySQL
前面詳細(xì)講述了 SQL 的注入過(guò)程,在注入其他數(shù)據(jù)庫(kù)時(shí),基本思路是相同的,只不過(guò)兩者使用的函數(shù)或者是語(yǔ)句稍有差異。
1. MySQL 中的注釋
MySQL 支持以下 3 中注釋風(fēng)格:
2. 獲取元數(shù)據(jù)
MySQL 5.0 及其以上版本提供了 ,這是一個(gè)信息數(shù)據(jù)庫(kù),它提供了訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)元數(shù)據(jù)的方式。下面介紹如何從中讀取數(shù)據(jù)庫(kù)名稱(chēng)、表名稱(chēng)以及列名稱(chēng)。
① 查詢(xún)用戶(hù)數(shù)據(jù)庫(kù)名稱(chēng)
FROM .
. 表提供了關(guān)于數(shù)據(jù)庫(kù)的信息。
②查詢(xún)當(dāng)前數(shù)據(jù)表
FROM . WHERE = ( ())
. 表給出了數(shù)據(jù)庫(kù)中表的信息。
③查詢(xún)指定表的所有字段
FROM . WHERE = '***'
. 表中給出了表中的列信息。
3. UNION 查詢(xún)
與 SQL 大致相同,此處不贅述。
4. MySQL 函數(shù)利用
無(wú)論是 MySQL、 還是其他數(shù)據(jù)庫(kù)都內(nèi)置了許多系統(tǒng)函數(shù),這些數(shù)據(jù)庫(kù)函數(shù)都非常類(lèi)似,接下來(lái)介紹一些對(duì)滲透測(cè)試人員很有幫助的 MySQL 函數(shù)。
① () 函數(shù)讀文件操作
MySQL 提供了 () 函數(shù),可以幫助用戶(hù)快速讀取文件,但文件的位置必須在服務(wù)器上,文件必須為絕對(duì)路徑,且用戶(hù)必須有 FILE 權(quán)限,文件容量也必須小于 字節(jié) (默認(rèn)為 16MB,最大為 1GB)。
SQL 語(yǔ)句如下:
UNION 1, ('/etc/'), 3, 4 #
通常一些防注入語(yǔ)句不允許單引號(hào)出現(xiàn),那么可以使用一下語(yǔ)句繞過(guò):
UNION 1, (), 3, 4 #
“” 為 “/etc/” 的十六進(jìn)制轉(zhuǎn)換結(jié)果。
在瀏覽器返回?cái)?shù)據(jù)時(shí),有可能存在亂碼問(wèn)題,那么可以使用 hex() 函數(shù)將字符串轉(zhuǎn)換為十六進(jìn)制數(shù)據(jù)。
② into 寫(xiě)文件操作
MySQL 提供了向磁盤(pán)寫(xiě)文件的操作,與 () 一樣,必須有 FILE 權(quán)限,并且文件必須為全路徑名稱(chēng)。
寫(xiě)入文件:
'' into 'C:\\1.php'
③ 連接字符串
MySQL 如果需要一次查詢(xún)多個(gè)數(shù)據(jù),可以使用 () 或 () 函數(shù)來(lái)完成。
name FROM WHERE id = 1 UNION (user(), ',', (), ',', ());
也可以將逗號(hào)改用十六進(jìn)制表示:0x2c
5. MySQL 顯錯(cuò)式注入
MySQL 也存在顯錯(cuò)式注入,可以像 SQL 數(shù)據(jù)庫(kù)那樣,使用錯(cuò)誤提取消息。
① 通過(guò) 函數(shù)執(zhí)行 SQL 語(yǔ)句
首先了解下()函數(shù):
(, , );
第一個(gè)參數(shù):是格式,為XML文檔對(duì)象的名稱(chēng);
第二個(gè)參數(shù): (Xpath格式的字符串) ,
第三個(gè)參數(shù):,格式,替換查找到的符合條件的數(shù)據(jù)
* FROM WHERE id = 1 and (1, ((0x7c, ( @@))), 1)
其中的()函數(shù)是將其連成一個(gè)字符串,因此不會(huì)符合的格式,從而出現(xiàn)格式錯(cuò)誤,報(bào)錯(cuò),會(huì)顯示出無(wú)法識(shí)別的內(nèi)容:
② 通過(guò) 函數(shù)
* FROM WHERE id= 1 AND (1, (0x7c, ( user())))
同樣報(bào)錯(cuò)顯示出當(dāng)前用戶(hù):
6. 寬字節(jié)注入
寬字節(jié)注入是由編碼不統(tǒng)一所造成的,這種注入一般出現(xiàn)在 PHP + MySQL中。
在 PHP 配置文件 php.ini 中存在 選項(xiàng),被稱(chēng)為魔術(shù)引號(hào),當(dāng)此選項(xiàng)被打開(kāi)時(shí),使用 GET、POST、 所接受的 單引號(hào)(’)、雙引號(hào)(")、反斜線(xiàn)() 和 NULL 字符都會(huì)自動(dòng)加上一個(gè)反斜線(xiàn)轉(zhuǎn)義。
如下使用 PHP 代碼使用 $_GET 接收參數(shù):
友情鏈接: 餐飲加盟
地址:北京市海淀區(qū) 電話(huà):010- 郵箱:@126.com
備案號(hào):冀ICP備2024067069號(hào)-3 北京科技有限公司版權(quán)所有