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

PHP 字符串過濾與防注入:從特殊字符清洗到 SQL 防禦的工程化方案

     編輯:PHP 綜合知識

誤區警示

原文通過 str_replace 黑名單過濾 and、select、union 等關鍵字,**極其危險**:

  • 大小寫繞過:UnIoN、SeLeCt
  • 編碼繞過:/*!UNION*/、0x73656c656374
  • 誤傷正常業務:用戶名「Alexander」被過濾為「Alexder」
  • 無法防禦二階注入、存儲型 XSS

正確防禦體系:分層防御

第一層:輸入驗證

// 白名單驗證:只允許預期格式
function validateUsername(string $input): string {
    if (!preg_match('/^[a-zA-Z0-9_\x{4e00}-\x{9fa5}]{3,20}$/u', $input)) {
        throw new \Exception('用戶名僅支持中英數下劃線,3-20 位');
    }
    return $input;
}

// 類型/長度/範圍強制
$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT, ['options'=>['min_range'=>1, 'max_range'=>120]]);

第二層:參數化查詢(核心防線)

// mysqli
$stmt = $mysqli->prepare('SELECT * FROM users WHERE username=? AND status=?');
$stmt->bind_param('si', $username, $status);
$stmt->execute();

// PDO(推薦)
$stmt = $pdo->prepare('SELECT * FROM users WHERE username=:u AND status=:s');
$stmt->execute([':u'=>$username, ':s'=>$status]);

第三層:輸出編碼(防 XSS)

// HTML 上下文
echo htmlspecialchars($userInput, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');

// JavaScript 上下文
echo json_encode($userInput, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP);

// URL 參數上下文
echo urlencode($userInput); // 或 rawurlencode

通用清洗函數(僅用於非結構化文本存儲/展示)

function cleanText(string $text, int $maxLen = 1000): string {
    // 1. 移除控制字符(保留換行/制表可選)
    $text = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', '', $text);
    // 2. 統一換行
    $text = str_replace(["\r\n", "\r"], "\n", $text);
    // 3. 限制長度
    if (mb_strlen($text, 'UTF-8') > $maxLen) {
        $text = mb_substr($text, 0, $maxLen, 'UTF-8');
    }
    // 4. 去首尾空白
    return trim($text);
}

富文本場景:HTMLPurifier 白名單過濾

composer require ezyang/htmlpurifier
require_once 'vendor/autoload.php';
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.Allowed', 'p,b,strong,i,em,u,strike,ul,ol,li,br,a[href|title],img[src|alt|width|height]');
$config->set('URI.AllowedSchemes', ['http'=>true, 'https'=>true, 'mailto'=>true]);
$purifier = new HTMLPurifier($config);
$safeHtml = $purifier->purify($dirtyHtml);

檔案上傳名稱安全化

function safeFilename(string $original): string {
    $ext = strtolower(pathinfo($original, PATHINFO_EXTENSION));
    $allowExt = ['jpg','jpeg','png','gif','webp','pdf','doc','docx','xls','xlsx'];
    if (!in_array($ext, $allowExt, true)) $ext = 'bin';
    return bin2hex(random_bytes(16)) . '.' . $ext;
}

總結:安全清單

  1. ❌ 永不 使用黑名單 str_replace 過濾 SQL 關鍵字。
  2. ✅ 始終 使用預處理語句(參數化查詢)。
  3. ✅ 輸入端 嚴格白名單驗證格式、長度、範圍。
  4. ✅ 輸出端 根據上下文編碼(HTML/JS/URL/CSS/SQL)。
  5. ✅ 富文本使用 HTMLPurifier 白名單標簽屬性。
  6. ✅ 文件名、路徑、命令參數等 絕不直接拼接,使用隨機名、escapeshellarg、realpath 校驗。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved