OWASP Top 10 - 注入攻擊原理與防護

OWASP Top 10 Injection Attack Principles and Prevention

什麼是注入攻擊

注入攻擊(Injection Attack)是 OWASP Top 10 中最常見且最危險的安全漏洞之一。當應用程式將不受信任的資料作為命令或查詢的一部分發送到解譯器時,就會發生注入漏洞。攻擊者可以利用惡意資料欺騙解譯器執行非預期的命令,或在未經適當授權的情況下存取資料。

注入攻擊可能發生在以下情況:

  • 使用者提供的資料未經驗證、過濾或清理
  • 動態查詢或非參數化呼叫直接使用於解譯器
  • 惡意資料被用於物件關聯對映(ORM)搜尋參數
  • 惡意資料被直接使用或串接到動態查詢、命令或預存程序中

常見的注入類型包括:SQL 注入、NoSQL 注入、OS 命令注入、LDAP 注入、XPath 注入等。

SQL 注入原理與範例

什麼是 SQL 注入

SQL 注入(SQL Injection)是最常見的注入攻擊類型。當應用程式將使用者輸入直接嵌入 SQL 查詢語句中,而未進行適當的驗證或編碼時,攻擊者可以操控 SQL 查詢來存取或修改資料庫中的資料。

基本 SQL 注入範例

假設有一個登入表單,後端使用以下 SQL 查詢:

1
SELECT * FROM users WHERE username = '$username' AND password = '$password'

如果攻擊者在使用者名稱欄位輸入:

1
admin' --

則 SQL 查詢變成:

1
SELECT * FROM users WHERE username = 'admin' --' AND password = ''

-- 是 SQL 的註解符號,後面的密碼檢查被註解掉了,攻擊者可以不需要密碼就登入 admin 帳號。

常見 SQL 注入類型

1. Union-based SQL Injection

利用 UNION 運算子合併多個 SELECT 語句的結果:

1
' UNION SELECT username, password FROM users --

2. Error-based SQL Injection

透過引發資料庫錯誤來獲取資訊:

1
' AND 1=CONVERT(int, (SELECT TOP 1 table_name FROM information_schema.tables)) --

3. Blind SQL Injection

當應用程式不顯示錯誤訊息時,可以透過觀察應用程式的回應來推斷資訊:

Boolean-based:

1
2
' AND 1=1 -- (回傳正常頁面)
' AND 1=2 -- (回傳不同頁面)

Time-based:

1
' AND SLEEP(5) -- (如果存在漏洞,回應會延遲 5 秒)

4. Stacked Queries

某些資料庫允許執行多個查詢:

1
'; DROP TABLE users; --

SQL 注入測試字串

以下是一些常用的測試字串:

1
2
3
4
5
6
7
8
9
'
"
`
')
")
`)
'))
"))
`))

其他類型的注入

Command Injection(命令注入)

當應用程式將使用者輸入傳遞給系統 shell 執行時,可能發生命令注入。

範例:

假設有一個 ping 功能:

1
2
$ip = $_GET['ip'];
system("ping -c 4 " . $ip);

攻擊者可以輸入:

1
127.0.0.1; cat /etc/passwd

結果會執行:

1
ping -c 4 127.0.0.1; cat /etc/passwd

常用的命令注入字元:

符號說明
;命令分隔符
|管道符號
&背景執行
&&AND 運算子
||OR 運算子
$()命令替換
`命令替換

LDAP Injection(LDAP 注入)

LDAP 注入發生在應用程式使用使用者輸入建構 LDAP 查詢時。

範例:

正常 LDAP 查詢:

1
(&(user=admin)(password=secret))

如果攻擊者輸入使用者名稱為:

1
admin)(&)

查詢變成:

1
(&(user=admin)(&))(password=任意值))

這可能繞過認證機制。

XPath Injection(XPath 注入)

類似 SQL 注入,但目標是 XML 文件的 XPath 查詢。

範例:

正常查詢:

1
//users/user[name='admin' and password='secret']

攻擊者輸入:

1
admin' or '1'='1

查詢變成:

1
//users/user[name='admin' or '1'='1' and password='']

NoSQL Injection(NoSQL 注入)

針對 NoSQL 資料庫(如 MongoDB)的注入攻擊。

範例(MongoDB):

1
2
3
4
5
6
7
8
// 正常查詢
db.users.find({username: "admin", password: "secret"})

// 攻擊輸入
{"$gt": ""}

// 結果查詢
db.users.find({username: "admin", password: {"$gt": ""}})

$gt 運算子表示「大於」,空字串幾乎大於所有值,因此繞過密碼檢查。

Template Injection(模板注入)

當使用者輸入被嵌入模板引擎時,可能發生伺服器端模板注入(SSTI)。

範例(Jinja2):

1
2
template = "Hello " + user_input
render(template)

攻擊者輸入:

1
{{7*7}}

如果回傳 Hello 49,表示存在模板注入漏洞。

防護措施

1. 使用參數化查詢(Parameterized Queries)

最有效的 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))

2. 輸入驗證(Input Validation)

  • 使用白名單驗證允許的輸入格式
  • 限制輸入長度
  • 驗證資料類型(數字、電子郵件等)
1
2
3
4
5
6
import re

def validate_username(username):
    if re.match(r'^[a-zA-Z0-9_]{3,20}$', username):
        return True
    return False

3. 輸出編碼(Output Encoding)

根據輸出的上下文進行適當的編碼:

  • HTML 編碼
  • URL 編碼
  • JavaScript 編碼

4. 最小權限原則

  • 資料庫帳號只給予必要的權限
  • 避免使用 root 或管理員帳號連接資料庫
  • 限制資料庫帳號只能存取特定的表格

5. 使用 ORM(物件關聯對映)

使用 ORM 框架可以減少直接撰寫 SQL 的機會:

1
2
# SQLAlchemy 範例
user = session.query(User).filter_by(username=username, password=password).first()

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

部署 WAF 可以偵測並阻擋常見的注入攻擊模式,但不應作為唯一的防護措施。

7. 錯誤處理

  • 不要向使用者顯示詳細的錯誤訊息
  • 記錄詳細錯誤到伺服器日誌
  • 向使用者顯示通用的錯誤訊息
1
2
3
4
5
try:
    # 資料庫操作
except Exception as e:
    logging.error(f"Database error: {e}")
    return "發生錯誤,請稍後再試"

測試方法

手動測試

  1. 識別注入點

    • 找出所有接受使用者輸入的地方
    • URL 參數、表單欄位、HTTP 標頭、Cookie 等
  2. 基本測試

    • 輸入特殊字元如 '";--
    • 觀察應用程式的回應和錯誤訊息
  3. 確認漏洞

    • 嘗試簡單的真假條件測試
    • ' OR '1'='1' OR '1'='2

自動化工具

SQLMap

SQLMap 是最常用的 SQL 注入自動化測試工具:

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

# 指定資料庫類型
sqlmap -u "http://target.com/page.php?id=1" --dbms=mysql

# 列出資料庫
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 --dump

Burp Suite

使用 Burp Suite 的 Scanner 功能可以自動偵測注入漏洞:

  1. 設定瀏覽器 Proxy 指向 Burp Suite
  2. 瀏覽目標網站
  3. 使用 Scanner 掃描特定請求
  4. 檢視掃描結果

OWASP ZAP

OWASP ZAP 是免費的 Web 應用程式安全測試工具:

  1. 設定 ZAP 作為 Proxy
  2. 使用 Spider 爬取網站
  3. 執行 Active Scan
  4. 檢視警報和漏洞報告

測試清單

  • 測試所有輸入欄位是否有 SQL 注入
  • 測試 HTTP 標頭(User-Agent、Cookie、Referer)
  • 測試 JSON/XML 請求主體
  • 測試命令注入漏洞
  • 測試 LDAP 注入
  • 測試 NoSQL 注入
  • 驗證錯誤處理是否洩漏敏感資訊

參考資源

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