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

PHP SQL 注入防禦實戰:addslashes、array_walk_recursive、Magic Quotes 與現代最佳實踐

     編輯:PHP 綜合知識

SQL 注入核心原理

// 正常預期
$id = 3;
$sql = "DELETE FROM news WHERE id = $id"; // DELETE FROM news WHERE id = 3

// 惡意構造
$id = "3 OR 1";
$sql = "DELETE FROM news WHERE id = $id"; // DELETE FROM news WHERE id = 3 OR 1 → 全表刪除

鐵律:永遠不信任客戶端輸入 ($_GET/$_POST/$_COOKIE/$_REQUEST/$_SERVER)。

傳統轉義方案演進

1. 手動 addslashes (僅處理單引號、雙引號、反斜杠、NUL)

foreach ($_POST as $k => $v) {
    if (is_string($v)) $_POST[$k] = addslashes($v);
}

2. 多維數組遞歸轉義

function _addslashes(&$value, $key) {
    $value = addslashes($value);
}
array_walk_recursive($_POST, '_addslashes');
array_walk_recursive($_GET, '_addslashes');
array_walk_recursive($_COOKIE, '_addslashes');

3. Magic Quotes (PHP 5.4 移除,歷史遺留)

// php.ini: magic_quotes_gpc = On
// 自動對 GPC 數據 addslashes

// 兼容代碼:防止雙重轉義
if (!get_magic_quotes_gpc()) {
    array_walk_recursive($_POST, '_addslashes');
    array_walk_recursive($_GET, '_addslashes');
    array_walk_recursive($_COOKIE, '_addslashes');
}

現代最佳實踐:預處理語句

轉義本質是字符串拼接的補丁,預處理從根源分離代碼與數據。

PDO (推薦,支援多數據庫)

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'user', 'pass', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES => false, // 使用真實預處理
]);

// 參數綁定
$stmt = $pdo->prepare('DELETE FROM news WHERE id = ?');
$stmt->execute([$_GET['id']]); // 自動處理類型、轉義、防注入

// 命名佔位符
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email AND status = :status');
$stmt->execute(['email' => $email, 'status' => 1]);

MySQLi (原生驅動)

<?php
$mysqli = new mysqli('localhost', 'user', 'pass', 'test');
$stmt = $mysqli->prepare('DELETE FROM news WHERE id = ?');
$stmt->bind_param('i', $_GET['id']); // i=integer, s=string, d=double, b=blob
$stmt->execute();

防禦深度清單

  1. 最小權限原則:Web 賬號僅擁有必要表的 SELECT/INSERT/UPDATE/DELETE,無 DROP/ALTER/TRUNCATE。
  2. 錯誤信息不外露:生產環境關閉 display_errors,記錄日誌而非輸出頁面。
  3. 輸入驗證白名單:ID 必須是正整數 ctype_digit()、(int)$_GET['id']、filter_var($id, FILTER_VALIDATE_INT)。
  4. ORM/Query Builder:Laravel Eloquent、ThinkPHP Db、Medoo 等框架層內建參數綁定。
  5. WAF/IDS:ModSecurity、OpenRASP 做最後一道防線。

總結

從 addslashes 到 Magic Quotes 再到預處理語句,PHP 防注入歷程是從「字符串修補」走向「代碼數據分離」。新項目無理由不使用 PDO/MySQLi 預處理,舊項目重構優先級最高。

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