返回首頁SQL

SQL Injection 完整攻防指南:原理解析與防範實戰【2025】

23 min 分鐘閱讀

SQL Injection 完整攻防指南:原理解析與防範實戰【2025】

SQL Injection 完整攻防指南:原理解析與防範實戰【2025】

根據 OWASP(開放網路應用程式安全專案)統計,SQL Injection 連續多年蟬聯 Web 應用程式十大安全風險排行榜,每年造成全球數十億美元的經濟損失。更令人擔憂的是,許多開發團隊至今仍對這種「古老」的攻擊手法缺乏足夠認識,導致新開發的系統依然存在漏洞。

本文將從攻擊者視角深入解析 SQL Injection 的運作原理,並提供完整的防範策略與程式碼範例,幫助開發者與資安人員建立堅固的資料庫安全防線。無論你是剛接觸資安的開發者,還是需要強化既有系統安全的技術主管,都能從本文獲得實用的防護知識。

插圖:SQL Injection 攻擊流程示意圖,展示惡意輸入如何竄改資料庫查詢

場景描述: 流程圖展示使用者輸入如何經過未驗證的程式碼直接拼接成 SQL 查詢,並被資料庫執行的完整攻擊流程。

視覺重點:

  • 主要內容清晰呈現

必須出現的元素:

  • 依據描述中的關鍵元素

需要顯示的中文字:

顏色調性: 專業、清晰

避免元素: 抽象圖形、齒輪、發光特效

Slug: sql-injection-attack-flow-diagram


SQL Injection 是什麼?

SQL Injection(SQL 注入攻擊,簡稱 SQLi)是一種透過在應用程式輸入欄位中插入惡意 SQL 程式碼,進而操控後端資料庫的攻擊手法。當應用程式未對使用者輸入進行適當驗證,直接將輸入內容拼接到 SQL 查詢語句中時,攻擊者就能藉此「注入」自己的 SQL 指令。

攻擊原理圖解

讓我們透過一個典型的登入頁面來理解攻擊原理:

-- 正常的登入查詢
SELECT * FROM users
WHERE username = '輸入的帳號' AND password = '輸入的密碼';

-- 當使用者輸入以下帳號時:
-- 帳號:admin'--
-- 密碼:任意

-- 實際執行的查詢變成:
SELECT * FROM users
WHERE username = 'admin'--' AND password = '任意';

-- '--' 是 SQL 註解符號,後面的密碼檢查被忽略
-- 攻擊者成功繞過身份驗證!

這就是 SQL Injection 的核心概念:利用字串拼接的漏洞,將攻擊者的 SQL 程式碼「注入」到原本的查詢中執行

SQL Injection 的危害程度

成功的 SQL Injection 攻擊可能造成以下後果:

危害類型說明嚴重程度
資料外洩竊取用戶個資、信用卡資訊、商業機密極高
資料竄改修改訂單金額、更改用戶權限、植入假資料
資料刪除清空資料表、破壞資料庫結構
權限提升取得管理員權限、存取受限功能
系統控制執行作業系統指令、植入後門程式極高

常見 SQL Injection 攻擊類型

SQL Injection 依據攻擊方式和回應特徵可分為多種類型,了解各類型的特點有助於建立更全面的防禦策略。

1. Classic SQL Injection(經典型)

經典型 SQL Injection 是最直接的攻擊方式,攻擊者可以從應用程式的回應中直接看到注入結果。

攻擊範例:

-- 原始查詢(商品搜尋功能)
SELECT * FROM products WHERE category = '使用者輸入';

-- 攻擊輸入:' UNION SELECT username, password FROM users--
-- 執行結果:
SELECT * FROM products WHERE category = ''
UNION SELECT username, password FROM users--';

-- 攻擊者直接在搜尋結果中看到所有用戶帳密

2. Blind SQL Injection(盲注型)

當應用程式不直接顯示查詢結果時,攻擊者透過觀察應用程式的「行為差異」來推斷資料內容。

Boolean-based(布林型盲注):

-- 透過頁面回應判斷條件真假
-- 測試第一個字元是否為 'a'
SELECT * FROM users WHERE id = 1 AND SUBSTRING(username,1,1) = 'a';

-- 如果頁面正常顯示,表示第一個字元是 'a'
-- 如果頁面異常,表示不是 'a',繼續測試下一個字元

Time-based(時間型盲注):

-- 利用延遲函數判斷條件
-- 如果管理員帳號第一個字元是 'a',則延遲 5 秒
SELECT * FROM users WHERE id = 1
AND IF(SUBSTRING(username,1,1)='a', SLEEP(5), 0);

-- 透過回應時間長短判斷條件是否成立

3. Union-based SQL Injection

利用 UNION 運算子將攻擊者的查詢結果合併到原始查詢中。

-- 必須先確定原始查詢的欄位數量
' ORDER BY 1-- (測試 1 個欄位)
' ORDER BY 2-- (測試 2 個欄位)
' ORDER BY 3-- (測試 3 個欄位,若報錯表示只有 2 個欄位)

-- 確定欄位數後進行注入
' UNION SELECT table_name, column_name FROM information_schema.columns--

-- 取得資料庫結構資訊

4. Error-based SQL Injection

利用資料庫錯誤訊息洩露的資訊進行攻擊。

-- SQL Server 錯誤型注入
' AND 1=CONVERT(int, (SELECT TOP 1 username FROM users))--

-- 錯誤訊息可能顯示:
-- "Conversion failed when converting the nvarchar value 'admin' to data type int"
-- 攻擊者從錯誤訊息中取得使用者名稱

各攻擊類型比較

攻擊類型偵測難度攻擊效率資訊取得方式
Classic直接從回應取得
Boolean-based逐字元推斷
Time-based極低透過時間延遲推斷
Union-based合併查詢結果
Error-based從錯誤訊息取得

真實世界案例分析

了解歷史上的重大 SQL Injection 事件,有助於體認這類攻擊的嚴重性。

案例一:Heartland Payment Systems(2008)

美國第五大支付處理公司 Heartland 因 SQL Injection 攻擊洩露超過 1.3 億筆 信用卡資料,造成約 1.4 億美元 損失,是當時史上最大的信用卡資料外洩事件。

案例二:Sony Pictures(2011)

駭客組織 LulzSec 利用 SQL Injection 入侵 Sony 多個網站,外洩超過 100 萬用戶 資料,包括密碼、電子郵件、住址等敏感資訊。

案例三:TalkTalk(2015)

英國電信公司 TalkTalk 遭受 SQL Injection 攻擊,導致 15 萬客戶 個資外洩,公司損失約 7,700 萬英鎊,並面臨監管機構 40 萬英鎊 罰款。

這些案例的共同點:

  • 攻擊手法並不複雜,多為基本的 SQL Injection
  • 防範措施早已存在,但未被正確實施
  • 造成的損失遠超過預防成本的數百倍

SQL Injection 防範策略

防範 SQL Injection 需要採取多層次的防禦策略,以下介紹經過驗證的最佳實踐方案。

1. 參數化查詢(Prepared Statements)

參數化查詢是防範 SQL Injection 最有效的方法,它將 SQL 語句結構與資料內容完全分離,確保使用者輸入永遠被當作「資料」而非「程式碼」處理。

Node.js + MySQL 範例:

// ❌ 危險:直接字串拼接
const query = `SELECT * FROM users WHERE username = '${username}' AND password = '${password}'`;

// ✅ 安全:參數化查詢
const query = 'SELECT * FROM users WHERE username = ? AND password = ?';
connection.execute(query, [username, password], (err, results) => {
    // 處理結果
});

Python + PostgreSQL 範例:

# ❌ 危險:直接字串拼接
cursor.execute(f"SELECT * FROM users WHERE username = '{username}'")

# ✅ 安全:參數化查詢
cursor.execute("SELECT * FROM users WHERE username = %s", (username,))

C# + SQL Server 範例:

// ❌ 危險:直接字串拼接
string query = $"SELECT * FROM users WHERE username = '{username}'";

// ✅ 安全:參數化查詢
string query = "SELECT * FROM users WHERE username = @username";
SqlCommand cmd = new SqlCommand(query, connection);
cmd.Parameters.AddWithValue("@username", username);

2. 使用 ORM 框架

ORM(Object-Relational Mapping)框架通常內建參數化查詢機制,可降低 SQL Injection 風險。

Entity Framework(C#)範例:

// 安全:LINQ 查詢自動參數化
var user = dbContext.Users
    .Where(u => u.Username == username && u.Password == password)
    .FirstOrDefault();

Django ORM(Python)範例:

# 安全:Django ORM 自動處理
user = User.objects.filter(username=username, password=password).first()

注意事項: 即使使用 ORM,仍需避免使用原始 SQL 拼接功能(如 Django 的 raw() 或 Entity Framework 的 FromSqlRaw())。

3. 輸入驗證與過濾

在參數化查詢的基礎上,增加輸入驗證可提供額外防護層。

// 白名單驗證範例
function validateSortColumn(input) {
    const allowedColumns = ['name', 'date', 'price', 'quantity'];
    if (allowedColumns.includes(input)) {
        return input;
    }
    return 'name'; // 預設值
}

// 格式驗證範例
function validateEmail(email) {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailRegex.test(email);
}

4. 最小權限原則

為資料庫帳號設定最小必要權限,限制攻擊成功後的損害範圍。

-- 為應用程式建立專用帳號
CREATE LOGIN app_user WITH PASSWORD = 'StrongPassword123!';
CREATE USER app_user FOR LOGIN app_user;

-- 只授予必要權限
GRANT SELECT, INSERT, UPDATE ON dbo.Products TO app_user;
GRANT SELECT ON dbo.Categories TO app_user;

-- 明確拒絕危險權限
DENY DELETE ON dbo.Users TO app_user;
DENY ALTER, DROP TO app_user;

插圖:資料庫權限層級架構圖,展示最小權限原則的實施方式

場景描述: 階層圖展示資料庫管理員、應用程式帳號、唯讀帳號的權限範圍差異,說明如何實施最小權限原則。

視覺重點:

  • 主要內容清晰呈現

必須出現的元素:

  • 依據描述中的關鍵元素

需要顯示的中文字:

顏色調性: 專業、清晰

避免元素: 抽象圖形、齒輪、發光特效

Slug: database-permission-hierarchy-diagram


企業資安防護需要專業評估 — CloudInsight 提供完整的資安弱點掃描服務,協助企業識別 SQL Injection 等潛在風險,建立符合 OWASP 標準的安全架構。立即預約資安評估諮詢


WAF 防火牆防護設定

Web Application Firewall(WAF)可在應用程式前端攔截常見的 SQL Injection 攻擊模式,作為第一道防線。

常見 WAF 解決方案

WAF 類型代表產品適用場景
雲端 WAFCloudflare、AWS WAF、Azure WAF雲端應用程式、CDN 整合
硬體 WAFF5 BIG-IP、Fortinet FortiWeb大型企業、高流量網站
軟體 WAFModSecurity、NAXSI自建主機、成本考量

ModSecurity 規則範例

# 阻擋 SQL 關鍵字
SecRule ARGS "@rx (?i)(union|select|insert|update|delete|drop)" \
    "id:1001,phase:2,deny,status:403,msg:'SQL Injection Attempt'"

# 阻擋 SQL 註解符號
SecRule ARGS "@rx (--|#|\/\*)" \
    "id:1002,phase:2,deny,status:403,msg:'SQL Comment Injection'"

# 阻擋單引號攻擊
SecRule ARGS "@rx '.*(\bor\b|\band\b).*'" \
    "id:1003,phase:2,deny,status:403,msg:'SQL Injection - Boolean'"

WAF 的限制

WAF 只是防禦策略的一環,不應作為唯一的防護手段:

  • 可能產生誤報:合法的包含 SQL 關鍵字的輸入可能被誤擋
  • 可被繞過:進階攻擊者可透過編碼、混淆等技術規避偵測
  • 效能影響:複雜的規則集可能增加延遲
  • 需持續更新:新的攻擊手法需要新的規則因應

安全測試工具

定期進行安全測試是發現 SQL Injection 弱點的重要手段。以下介紹兩款主流工具。

SQLMap

SQLMap 是最知名的開源 SQL Injection 自動化測試工具,支援多種資料庫和攻擊技術。

基本使用範例:

# 測試單一參數
sqlmap -u "http://example.com/page?id=1" --dbs

# 測試 POST 請求
sqlmap -u "http://example.com/login" --data="user=test&pass=test" --dbs

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

# 取得特定表格資料
sqlmap -u "http://example.com/page?id=1" -D database_name -T users --dump

常用參數說明:

參數說明
--dbs列出所有資料庫
--tables列出資料表
--columns列出欄位
--dump匯出資料
--risk風險等級(1-3)
--level測試深度(1-5)

Burp Suite

Burp Suite 是專業的 Web 應用程式安全測試平台,提供手動與自動化測試功能。

SQL Injection 測試流程:

  1. 設定代理:將瀏覽器流量導向 Burp Proxy
  2. 攔截請求:捕獲目標應用程式的 HTTP 請求
  3. 送至 Repeater:手動測試各種注入 payload
  4. 使用 Intruder:自動化測試多種注入變體
  5. 使用 Scanner:自動掃描 SQL Injection 弱點

測試 Payload 範例:

' OR '1'='1
' OR '1'='1'--
' UNION SELECT NULL--
' UNION SELECT NULL, NULL--
1' AND '1'='1
1' AND '1'='2
1' AND SLEEP(5)--

SQL Injection 安全檢查清單

以下是開發團隊應執行的安全檢查項目:

程式碼層面

  • 所有 SQL 查詢使用參數化查詢或 Prepared Statements
  • 動態表格/欄位名稱使用白名單驗證
  • 不使用字串拼接建構 SQL 語句
  • ORM 原始查詢功能有適當參數化
  • 輸入資料有基本格式驗證

資料庫層面

  • 應用程式使用專用的低權限帳號連線
  • 敏感資料已加密儲存(如密碼使用 bcrypt)
  • 已停用不必要的資料庫功能(如 xp_cmdshell)
  • 錯誤訊息不洩露資料庫結構資訊
  • 定期備份並測試還原程序

架構層面

  • 已部署 WAF 並設定適當規則
  • 應用程式與資料庫位於不同網路區段
  • 已啟用資料庫稽核日誌
  • 有異常流量監控與警報機制
  • 定期進行滲透測試

開發流程

  • 程式碼審查包含安全性檢查項目
  • CI/CD 管線整合 SAST(靜態程式碼分析)工具
  • 開發團隊有 SQL Injection 防護培訓
  • 有資安事件應變計畫
  • 定期更新資料庫與框架版本

插圖:SQL Injection 防護架構總覽圖,展示多層次防禦策略

場景描述: 架構圖展示從使用者端到資料庫的完整防護層次,包括 WAF、輸入驗證、參數化查詢、最小權限等多層防禦機制。

視覺重點:

  • 主要內容清晰呈現

必須出現的元素:

  • 依據描述中的關鍵元素

需要顯示的中文字:

顏色調性: 專業、清晰

避免元素: 抽象圖形、齒輪、發光特效

Slug: sql-injection-defense-architecture-overview


常見問題 FAQ

Q1:SQL Injection 攻擊有多常見?

根據 Verizon 2024 年資料外洩調查報告,Web 應用程式攻擊仍是資料外洩的主要管道之一,其中 SQL Injection 是最常被利用的弱點類型之一。Akamai 的統計顯示,SQL Injection 攻擊佔所有 Web 應用程式攻擊的約 65%。即使這是已知超過 20 年的攻擊手法,至今仍有大量網站存在此弱點,主要原因是許多開發者缺乏安全意識,或在時程壓力下忽略安全實踐。

Q2:使用 ORM 就不會有 SQL Injection 嗎?

使用 ORM 框架確實能大幅降低 SQL Injection 風險,因為 ORM 預設使用參數化查詢。然而,這並不代表絕對安全。以下情況仍可能產生弱點:(1) 使用 ORM 的原始 SQL 執行功能(如 Django 的 raw())時直接拼接字串;(2) 動態建構 ORDER BY 或表格名稱時未做驗證;(3) 使用較舊版本的 ORM 且存在已知弱點。建議的做法是:使用 ORM 標準查詢方法、避免原始 SQL、定期更新 ORM 版本,並對動態欄位名稱使用白名單驗證。

Q3:如何測試網站是否有 SQL Injection 弱點?

有幾種測試方法:(1) 手動測試:在輸入欄位嘗試加入單引號 ' 或其他 SQL 特殊字元,觀察是否出現資料庫錯誤訊息;(2) 自動化工具:使用 SQLMap、Burp Suite 等專業工具進行系統性測試;(3) 靜態程式碼分析:使用 SonarQube、Checkmarx 等 SAST 工具掃描原始碼;(4) 滲透測試:聘請專業資安團隊進行完整的應用程式安全評估。建議企業至少每年進行一次專業滲透測試,並在重大版本更新後進行安全掃描。


延伸學習資源

深入學習 SQL 與資安相關知識,建議參考以下資源:

SQL 基礎與進階:

SQL Server 相關:

雲端與進階主題:


結論

SQL Injection 是一種「古老但致命」的攻擊手法,防範方法早已成熟且廣為人知,但實際執行率卻遠低於預期。根據本文的討論,最關鍵的防護措施是:始終使用參數化查詢。這是防範 SQL Injection 最有效、最直接的方法,配合最小權限原則、輸入驗證、WAF 部署等多層次防禦,可大幅降低資料庫被攻擊的風險。

安全不是一次性的工作,而是持續的過程。建議開發團隊將安全意識融入日常開發流程,從程式碼審查、自動化測試到定期滲透測試,建立完整的安全生命週期管理。


建立安全的資料庫環境需要專業協助 — CloudInsight 提供企業資料庫安全評估服務,從架構設計、程式碼審查到滲透測試,全方位強化您的資料庫防護能力。立即聯繫我們,讓專業團隊為您的系統安全把關。

預約企業資料庫安全評估諮詢 →


參考資料

需要專業的雲端建議?

無論您正在評估雲平台、優化現有架構,或尋找節費方案,我們都能提供協助

預約免費諮詢

相關文章