萬盛學電腦網

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

防止 SQL 注入攻擊完整防禦指南:參數化查詢、輸入驗證、最小權限

SQL 注入 是最嚴重的 Web 安全漏洞之一。本文系統整理防禦層次:參數化查詢 (核心)、輸入驗證、最小權限、WAF、審計日誌。

核心防禦:參數化查詢 (Prepared Statements)

永遠不要用字串拼接 SQL。使用預處理語句,參數以佔位符傳遞,資料庫引擎將程式碼與資料分離。

PDO 範例

<?php
$pdo = new PDO($dsn, $user, $pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);

// 安全:佔位符 ?
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ? AND status = ?');
$stmt->execute([$_POST['email'], 'active']);
$user = $stmt->fetch();

// 命名參數 (更易讀)
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->execute([':email' => $_POST['email']]);

mysqli 範例

$stmt = $mysqli->prepare('SELECT * FROM users WHERE email = ?');
$stmt->bind_param('s', $_POST['email']);
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();

輔助防禦層

1. 強制型別轉換

$id = (int)$_GET['id'];        // 整數
$price = (float)$_POST['price']; // 浮點數

2. 白名單驗證

$allowedSort = ['name', 'created_at', 'price'];
$sort = in_array($_GET['sort'], $allowedSort) ? $_GET['sort'] : 'created_at';
$order = ($_GET['order'] ?? 'DESC') === 'ASC' ? 'ASC' : 'DESC';
$sql = "SELECT * FROM products ORDER BY $sort $order"; // 欄位名無法參數化,必須白名單

3. 字元過濾/轉義 (次要,不替代參數化)

$mysqli->real_escape_string($str);  // mysqli
$pdo->quote($str);                  // PDO (含引號)
僅作為深度防禦,不可作為主要防線。

4. 最小權限資料庫帳號

  • Web 應用帳號:僅 SELECT, INSERT, UPDATE, DELETE 業務表,無 DROP/ALTER/GRANT。
  • 遷移/部署腳本使用擁有 DDL 權限的獨立帳號。
  • 唯讀報表帳號:僅 SELECT。

5. 避免動態 SQL (Stored Procedure 亦需參數化)

-- 不安全動態 SQL
SET @sql = CONCAT('SELECT * FROM ', @table);
PREPARE stmt FROM @sql;  -- 仍有風險若 @table 來自用戶輸入

-- 安全:白名單驗證表名後再拼接

常見注入 Payload 範例 (僅供防禦測試)

  • ' OR '1'='1
  • '; DROP TABLE users; --
  • UNION SELECT password FROM admin --
  • 1; WAITFOR DELAY '0:0:5' -- (時間盲注)

綜合防禦清單

  1. ✅ 所有查詢使用參數化語句
  2. ✅ 輸入驗證:型別、長度、格式、白名單
  3. ✅ 資料庫帳號最小權限
  4. ✅ 錯誤訊息不回顯給前端 (關閉 display_errors)
  5. ✅ WAF (ModSecurity/Cloudflare) 規則攔截已知攻擊特徵
  6. ✅ 審計日誌記錄所有失敗登入、異常查詢
  7. ✅ 定期滲透測試與程式碼審查

框架內建防護

  • Laravel Eloquent / Query Builder:自動參數化
  • PDO / mysqli 正確用法:參數化
  • ThinkPHP / Yii / CodeIgniter:Active Record / Query Builder 參數化
只要堅持「查詢結構與資料分離」,SQL 注入即可徹底根除。
copyright © 萬盛學電腦網 all rights reserved