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

PHP $_GET/$_POST SQL 注入防禦:addslashes_deep 全域過濾實作與局限

     編輯:PHP 綜合知識

早期 PHP 專案常在入口檔案引入全域過濾腳本,對 $_GET、$_POST、$_COOKIE、$_REQUEST 統一執行 addslashes_deep,試圖以「一次轉義、到處安全」阻擋 SQL 注入。本文還原經典實作,剖析其防禦範圍、繞過手法與現代替代方案。

經典全域過濾代碼

if (!get_magic_quotes_gpc()) { // PHP 5.4+ 已移除,此判斷恆為 true
    if (!empty($_GET))    $_GET    = addslashes_deep($_GET);
    if (!empty($_POST))   $_POST   = addslashes_deep($_POST);
    $_COOKIE  = addslashes_deep($_COOKIE);
    $_REQUEST = addslashes_deep($_REQUEST);
}

function addslashes_deep($value) {
    if (empty($value)) return $value;
    return is_array($value)
        ? array_map('addslashes_deep', $value)
        : addslashes($value);
}

防禦效果與盲區

攻擊向量是否防禦說明
id=1' OR '1'='1 (值注入)✅ 防禦單引號被轉義為 \'
id=1; DROP TABLE users (值注入)✅ 防禦分號、空格不受影響,但單引號阻斷字串閉合
order_by=name;-- (鍵名注入)❌ 失效addslashes_deep 不處理鍵名
id=1/*!UNION*/SELECT... (註解繞過)⚠️ 視情況無單引號時可能繞過,需結合關鍵字過濾
二次注入 (存儲惡意資料,後續拼接)❌ 失效入庫時已轉義,讀出再拼接時單引號變雙重轉義,但若開發者用 stripslashes 會復原
編碼繞過 (GBK 多字節、Unicode)❌ 失效addslashes 不具備字元集感知,易被寬字節攻擊

為什麼不再推薦全域 addslashes?

  1. 偽安全感:開發者誤以為「已過濾」而疏忽參數化查詢,反而增加風險。
  2. 汙染原始資料:導致正常文字(如 O'Reilly)在顯示層出現多餘反斜線,需額外 stripslashes,易造成雙重轉義/漏轉義。
  3. 效能浪費:對所有輸入遞迴處理,含非 SQL 語境資料(如檔案上傳、JSON API)。
  4. 不相容現代框架:Laravel、Symfony、ThinkPHP 5+ 皆採用參數化查詢,全域轉義會干擾 ORM 正常運作。

現代最佳實踐:分層防禦

// 1. 邊界層:表單驗證(白名單、型別、長度、格式)
$request->validate([
    'id' => 'required|integer|min:1',
    'order_by' => 'in:id,name,created_at', // 白名單
]);

// 2. 資料層:參數化查詢(PDO / Eloquent / ThinkPHP)
// PDO
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id ORDER BY :order');
$stmt->execute(['id' => $id, 'order' => $orderBy]);

// ThinkPHP 5+
User::where('id', $id)->order($orderBy)->select();

// 3. 輸出層:語境編碼
// HTML: htmlspecialchars($str, ENT_QUOTES, 'UTF-8')
// JS:   json_encode($str)
// SQL:  參數化已處理,無需額外編碼

遺留專案升級路徑

  1. 移除全域 addslashes_deep 呼叫。
  2. 啟用框架內建參數化查詢(ThinkPHP where()、Laravel Eloquent)。
  3. 逐模組補齊驗證規則(Request 驗證器)。
  4. 掃描 stripslashes、mysql_real_escape_string 等舊代碼並重構。
  5. 引入靜態分析工具(PHPStan + PHPStan-Security)攔截拼接 SQL 模式。

總結

addslashes_deep 全域過濾是**「以犧牲資料完整性換取部分防禦」**的妥協產物,已不適合現代 PHP 開發。徹底擁抱**參數化查詢 + 邊界驗證 + 輸出編碼**三層架構,才是 SQL 注入防禦的正解。

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