SQL 注入是 Web 應用最頂級的安全威脅之一。雖然現代框架(Laravel、Symfony、ThinkPHP 等)內建 ORM/Query Builder 可自動參數化查詢,但大量存量專案仍使用原生 mysql_query / mysqli / PDO 拼接 SQL。對這類專案,在入口處統一對超全域變數進行轉義,可作為「二線防禦」顯著降低風險。
<?php
/**
* 遞迴對陣列或純量值執行 addslashes
* 適用於 PHP 5.4+(已移除 magic_quotes_gpc)
*/
function addslashes_deep($value) {
if (empty($value)) {
return $value;
}
return is_array($value)
? array_map('addslashes_deep', $value)
: addslashes($value);
}
/**
* 統一過濾入口:在 common.inc.php / bootstrap.php 最早引入處調用
*/
function global_input_filter() {
// PHP 5.4+ 預設關閉 magic_quotes_gpc,無需判斷
// 若維護極舊專案(PHP < 5.4),可保留 get_magic_quotes_gpc() 判斷
$_GET = addslashes_deep($_GET);
$_POST = addslashes_deep($_POST);
$_COOKIE = addslashes_deep($_COOKIE);
$_REQUEST = addslashes_deep($_REQUEST); // 依賴 request_order 配置
}
// 立即執行
global_input_filter();
addslashes 僅轉義單引號、雙引號、反斜線、NUL,無法防禦所有注入向量(如數值型注入、編碼繞過)。$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?'); $stmt->execute([$id]);addslashes 會導致資料庫存入 O\'Reilly 等多重轉義字串。// $_FILES 不需轉義,但需嚴格驗證副檔名、MIME、內容
// 多維陣列已由 array_map 遞迴處理
php.ini 設定 default_charset = "UTF-8",資料庫連線亦使用 SET NAMES utf8mb4,避免編碼不一致導致繞過。| 方案 | 適用場景 | 優勢 |
|---|---|---|
| PDO + 預處理語句 | 所有新專案、重構專案 | 徹底分離代碼與資料、支援多種資料庫、效能更好 |
| Eloquent / Doctrine ORM | Laravel / Symfony 專案 | 物件導向查詢、自動參數化、關聯載入 |
| WAF (ModSecurity + OWASP CRS) | 生產環境邊界防護 | 攔截已知攻擊載荷、虛擬補丁、零代碼變更 |
| RASP (OpenRASP / 百度開源) | 運行時應用自我防護 | 精準檢測 SQL 注入、命令執行、反序列化等高危行為 |
本文提供的 addslashes_deep 方案適合**無法立即重構的舊專案**作為緊急加固手段。長期來說,請規劃遷移至參數化查詢 + WAF/RASP 的纏繞防禦架構,從根本上消除 SQL 注入風險。