萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

SQL 注入攻擊原理與防禦:從繞過 WAF 到參數化查詢的完整防護指南

⚠️ 法律與道德聲明

本文旨在協助開發者理解 SQL 注入攻擊向量,以建構更安全的應用程式。**嚴禁將此技術用於未經授權的系統測試或攻擊。** 請遵守當地法律法規與《電腦犯罪條例》等相關規定。

核心成因

應用程式將使用者輸入**直接拼接**進 SQL 語句,未經嚴格驗證或參數化,導致惡意輸入改變 SQL 語義。

常見攻擊手法與繞過技巧(僅供防禦參考)

技巧原理防禦對策
ORDER BY 探測欄位數 遞增數字直到報錯,推斷欄位數 參數化查詢;錯誤訊息不回顯前端
GROUP BY 替代 ORDER BY 繞過針對 ORDER BY 的 WAF 規則 WAF 規則需涵蓋同義語句;根本靠參數化
(SELECT * FROM t) = (SELECT 1) 強制報錯洩露欄位數 利用子查詢欄位數不匹配報錯回顯 統一錯誤頁面,不回顯資料庫錯誤細節
UNION SELECT 聯合查詢竊取資料 將惡意查詢結果併入正常結果集 嚴格輸入驗證、最小權限帳號、參數化
information_schema 列舉結構 查詢系統表取得資料庫/表/欄位名 資料庫帳號僅授予業務所需最小權限
INSERT/UPDATE/DROP 破壞資料 多語句執行(若驅動支援)執行寫入操作 帳號無 INSERT/UPDATE/DROP 權限;禁用多語句

根本防禦:參數化查詢

唯一可靠防線——永遠使用預備語句,將資料與代碼徹底分離。

PHP (PDO) 範例

$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id AND status = :status');
$stmt->execute([':id' => $input_id, ':status' => 1]);
$rows = $stmt->fetchAll();

Java (JDBC) 範例

PreparedStatement ps = conn.prepareStatement(
    "SELECT * FROM users WHERE id = ? AND status = ?");
ps.setInt(1, inputId);
ps.setInt(2, 1);
ResultSet rs = ps.executeQuery();

Python (PyMySQL) 範例

cursor.execute("SELECT * FROM users WHERE id = %s AND status = %s", (input_id, 1))

輔助防禦層

  • 最小權限原則:應用布號僅擁有業務必需的 SELECT/INSERT/UPDATE,嚴禁 DROP/ALTER/GRANT。
  • 輸入驗證與白名單:整數欄位用 intval(),列舉值用 in_array() 驗證。
  • 錯誤資訊隱藏:生產環境關閉 display_errors,統一友善錯誤頁,詳細錯誤寫入日誌供開發排查。
  • WAF/IDS:部署 ModSecurity 等 Web 應用防火牆作為第二道防線,**不可作為唯一依賴**。
  • 資料庫審計日誌:開啟 general_log 或审计插件,異常 SQL 即時告警。

程式碼審查檢查清單

  1. 是否存在字串拼接 SQL?
  2. 所有動態參數是否使用參數化?
  3. 錯誤回顯是否已關閉?
  4. 資料庫帳號權限是否最小化?
  5. 是否有針對高風險操作(刪除、修改密碼)的二次驗證?
copyright © 萬盛學電腦網 all rights reserved