SQL 注入仍是 Web 應用頭號安全風險。雖然 PHP 提供 mysql_real_escape_string 等轉義函數,但單純依賴轉義存在繞過風險。本文深入分析轉義機制局限,並推薦參數化查詢作為根本解決方案。
測試資料含特殊字符:
INSERT INTO `user` VALUES ('1', ''\\'''\\\'');
直接查詢會語法錯誤:
SELECT * FROM user WHERE name = "'\'''\'"; -- 錯誤
需手動轉義後才能查詢:
SELECT * FROM user WHERE name = "'\\'''\\\'"; -- 正確
mysql_escape_string:不考慮連線字符集,已棄用mysql_real_escape_string:依賴連線字符集,但無法防禦所有注入向量(如數字型注入、編碼繞過)str_replace 黑名單:維護成本高、易漏掉特殊字符、無法處理編碼變體嘗試用正則攔截 select|insert|update|delete 等關鍵字:
function inject_check($sql_str) {
return eregi('select|insert|update|delete|\'|', $sql_str);
}
致命缺陷:
user_select、update_time)使用預處理語句,資料與代碼徹底分離:
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$stmt = $pdo->prepare('SELECT * FROM user WHERE name = ? AND status = ?');
$stmt->execute([$name, $status]);
$rows = $stmt->fetchAll();
$mysqli = new mysqli('localhost', 'user', 'pass', 'test');
$stmt = $mysqli->prepare('SELECT * FROM user WHERE name = ?');
$stmt->bind_param('s', $name);
$stmt->execute();
$result = $stmt->get_result();
sql_mode=STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION 提高嚴格度字符轉義只是輔助手段,參數化查詢才是防禦 SQL 注入的銀彈。現代 PHP 開發應完全棄用 mysql_* 系列函數,全面採用 PDO/MySQLi 預處理語句,配合輸入驗證與最小權限原則,構建多層防禦體系。