現代網頁應用程式的 SQL 注入防範

Security2026-09-12TryQuickToolBox

SQL 注入仍然是最關鍵的網頁應用程式漏洞之一。攻擊者利用它來竊取資料、繞過身分驗證,甚至執行系統命令。如果你的應用程式透過串接使用者輸入來建構 SQL 查詢,你就處於風險之中。本文說明 SQL 注入的運作方式,並提供在現代網頁應用程式中防範的實用步驟。

SQL 注入如何發生

當不受信任的資料被解譯為 SQL 命令的一部分時,就會發生 SQL 注入。例如,考慮一個使用以下查詢檢查憑證的登入表單:

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

如果攻擊者輸入 ' OR '1'='1 作為使用者名稱,並輸入任意密碼,查詢會變成:

SELECT * FROM users WHERE username = '' OR '1'='1' AND password = 'anything';

這會傳回所有使用者,繞過身分驗證。類似的技術可以擷取資料、修改記錄或刪除資料表。

1. 使用預備陳述式(參數化查詢)

預備陳述式將 SQL 程式碼與資料分離。資料庫先接收查詢結構,然後接收參數,因此使用者輸入永遠不會被視為 SQL 程式碼。這是最有效的防禦措施。

PHP 搭配 PDO 的範例:

$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->execute(['email' => $userInput]);
$user = $stmt->fetch();

Java 搭配 JDBC 的範例:

String sql = "SELECT * FROM users WHERE email = ?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, userInput);
ResultSet rs = stmt.executeQuery();

對於所有使用者提供的資料,包括搜尋欄位、篩選條件和排序參數,都應一律使用參數化查詢。

2. 驗證與清理輸入

雖然預備陳述式是主要防禦,但輸入驗證可增加縱深防禦。驗證輸入是否符合預期模式(例如電子郵件格式、數字 ID),並拒絕任何非預期的內容。例如,如果 ID 應該是整數,請在程式碼中將其轉型為 int。避免使用引號等字元的黑名單——攻擊者可以繞過這類篩選。

3. 安全地使用 ORM

Hibernate、Entity Framework 和 Sequelize 等 ORM 通常預設使用參數化查詢。然而,它們經常允許原始 SQL 片段。對於接受原始字串的方法要謹慎:

請務必查閱你的 ORM 文件,了解安全的查詢建構方式。

4. 若無法使用預備陳述式,請對資料進行跳脫

在極少數情況下,當你必須建構動態 SQL(例如動態資料表名稱)時,請使用資料庫驅動程式的跳脫函式。對於 MySQL,mysqli_real_escape_string() 會跳脫特殊字元。但請記住:跳脫不如預備陳述式穩健,應作為最後手段。

5. 對資料庫帳戶套用最小權限原則

不要以 root 或具有完整權限的使用者身分連線至資料庫。為你的應用程式建立專用的資料庫使用者,僅賦予必要的權限(特定資料表上的 SELECT、INSERT、UPDATE、DELETE)。這可在發生注入時限制損害。

6. 使用網頁應用程式防火牆(WAF)

WAF 可以偵測並封鎖常見的 SQL 注入模式。雖然不能取代安全編碼,但它提供了額外的一層防護。許多雲端供應商提供易於啟用的受管 WAF。

7. 定期進行安全測試

使用自動化掃描器或手動滲透測試,來測試你的應用程式是否有 SQL 注入漏洞。SQLMap 等工具可協助識別問題。將安全測試整合至你的 CI/CD 流程中,以便及早發現回歸問題。

防範技術比較

技術 有效性 實作難易度
預備陳述式 高 容易(多數驅動程式內建)
輸入驗證 中 中等
安全使用 ORM 高 若有意識則容易
跳脫 中 容易但易出錯
最小權限 中 容易
WAF 低至中 容易(受管)

常見問題

防範 SQL 注入最有效的方法是什麼?

使用預備陳述式搭配參數化查詢是最有效的方法。它確保使用者輸入永遠不會被解譯為 SQL 程式碼。

僅靠輸入驗證能防範 SQL 注入嗎?

不能。輸入驗證是良好的縱深防禦措施,但不應僅依賴它。攻擊者有時可以繞過驗證規則,因此請一律使用預備陳述式作為主要防禦。

ORM 是否自動對 SQL 注入免疫?

ORM 在正確使用時通常是安全的,但它們經常允許原始 SQL 查詢,若你串接使用者輸入,就可能存在漏洞。即使在 ORM 方法中,也請一律使用參數化查詢。

如需額外的安全性,可考慮使用 JSON formatter 來安全地檢查和驗證 API 回應,而不會執行惡意程式碼。