首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 實現 $_GET $_POST $_COOKIE 全域過濾防 SQL 注入的最佳實踐

     編輯:PHP 相關知識

背景與風險

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();

關鍵細節與避坑指南

1. 僅作為「二線防禦」,不可替代參數化查詢

  • addslashes 僅轉義單引號、雙引號、反斜線、NUL,無法防禦所有注入向量(如數值型注入、編碼繞過)。
  • **核心防線永遠是預處理語句**:$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?'); $stmt->execute([$id]);

2. 避免雙重轉義導致資料污染

  • 若框架已在 Model 層自動轉義,入口處再次 addslashes 會導致資料庫存入 O\'Reilly 等多重轉義字串。
  • 解決:在框架初始化**之前**執行本函數,或在框架配置中關閉內建轉義(如 Laravel 不需此層)。

3. 處理多維陣列與檔案上傳

// $_FILES 不需轉義,但需嚴格驗證副檔名、MIME、內容
// 多維陣列已由 array_map 遞迴處理

4. 編碼一致性

  • 確保 php.ini 設定 default_charset = "UTF-8",資料庫連線亦使用 SET NAMES utf8mb4,避免編碼不一致導致繞過。

現代化替代方案(強烈推薦)

方案適用場景優勢
PDO + 預處理語句所有新專案、重構專案徹底分離代碼與資料、支援多種資料庫、效能更好
Eloquent / Doctrine ORMLaravel / Symfony 專案物件導向查詢、自動參數化、關聯載入
WAF (ModSecurity + OWASP CRS)生產環境邊界防護攔截已知攻擊載荷、虛擬補丁、零代碼變更
RASP (OpenRASP / 百度開源)運行時應用自我防護精準檢測 SQL 注入、命令執行、反序列化等高危行為

總結

本文提供的 addslashes_deep 方案適合**無法立即重構的舊專案**作為緊急加固手段。長期來說,請規劃遷移至參數化查詢 + WAF/RASP 的纏繞防禦架構,從根本上消除 SQL 注入風險。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved