SQL 注入是 Web 應用頭號威脅。PHP 早期常用 addslashes,但對多位元組字符集(GBK、UTF-8)存在繞過風險。本文深度解析三大轉義函數差異,並給出現代最佳實踐。
| 函數 | 轉義字符 | 字符集感知 | PHP 版本狀態 |
|---|---|---|---|
addslashes | ' " \ NULL | ❌ 無 | 全版本可用 |
mysql_escape_string | \x00 \n \r \ ' " \x1a | ❌ 無 | PHP 5.3 棄用,7.0 移除 |
mysql_real_escape_string | \x00 \n \r \ ' " \x1a | ✅ 有(需連線) | PHP 5.3+ 可用,7.0 移除 |
GBK 編碼下,攻擊者可送入 0xBF27(單位元組 ' 經過 addslashes 變 0xBF5C27),0xBF5C 為合法雙位元組字符,導致單引號「倖存」並閉合 SQL 字串。
$stmt = $pdo->prepare('SELECT * FROM users WHERE name = ?');
$stmt->execute([$name]);$safe = $pdo->quote($input); // 含引號
$safe = $mysqli->real_escape_string($input);SET NAMES utf8mb4 或 DSN 指定 charset=utf8mb4,確保轉義函數與資料庫字符集一致。若暫時無法改用預處理,請將所有 addslashes($input) 替換為 mysql_real_escape_string($input)(需在 mysql_connect 之後呼叫),並確認連線字符集為 utf8mb4 或 gbk。
addslashes 僅適用單位元組字符集,嚴禁用於 GBK/UTF-8 環境。mysql_escape_string 已移除,不可使用。mysql_real_escape_string 雖有字符集感知,但屬 mysql_* 擴展(已移除),新專案請直接用 PDO/MySQLi 預處理。