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

PHP mb_check_encoding 詳解:防範無效編碼攻擊的實戰指南

     編輯:PHP 相關知識

函數簽名與說明

bool mb_check_encoding ( string|null $string = null, string|null $encoding = null ): bool
  • $string:待檢查字節流,省略時檢查所有請求輸入($_GET、$_POST、$_COOKIE 等)。
  • $encoding:目標編碼,默認 mb_internal_encoding()。
  • 返回 true 表示通過驗證,false 表示存在無效字節序列。
核心價值:有效防範「無效編碼攻擊」,攻擊者通過構造非法字節序列繞過安全檢查、導致邏輯漏洞或緩衝區溢出。

基本用法示例

<?php
// 檢查單個字符串是否為合法 UTF-8
$str = "正常中文";
var_dump(mb_check_encoding($str, 'UTF-8')); // true

// 檢查包含非法字節的字符串
$bad = "正常\xC0\xAF中文"; // \xC0\xAF 為非法 UTF-8 序列
var_dump(mb_check_encoding($bad, 'UTF-8')); // false

// 批量檢查請求輸入(省略參數)
if (!mb_check_encoding(null, 'UTF-8')) {
    die('請求包含非法編碼,疑似攻擊');
}

手寫 UTF-8 驗證算法(教學用)

若環境無 mbstring 擴展,可參考以下純 PHP 實現(摘自原文並優化註釋):

<?php
function check_utf8($str)
{
    $len = strlen($str);
    for ($i = 0; $i < $len; $i++) {
        $c = ord($str[$i]);
        if ($c <= 127) {
            continue; // ASCII 字符,單字節
        }
        // 多字節序列首字節判斷
        if ($c > 247) return false;           // 5-6 字節(UTF-8 實際只到 4 字節)
        elseif ($c > 239) $bytes = 4;         // 11110xxx
        elseif ($c > 223) $bytes = 3;         // 1110xxxx
        elseif ($c > 191) $bytes = 2;         // 110xxxxx
        else return false;                    // 10xxxxxx 不能作為首字節

        // 檢查剩餘長度
        if (($i + $bytes) > $len) return false;

        // 校驗後續字節:必須為 10xxxxxx (128-191)
        while (--$bytes > 0) {
            $i++;
            $b = ord($str[$i]);
            if ($b < 128 || $b > 191) return false;
        }
    }
    return true;
}

實戰場景與最佳實踐

1. 輸入驗證中間件(框架無關)

<?php
// 簡易中間件示例
function validateEncodingMiddleware(callable $next)
{
    if (!mb_check_encoding(null, 'UTF-8')) {
        http_response_code(400);
        exit('Invalid encoding detected');
    }
    return $next();
}

2. 文件上傳內容檢查

<?php
$content = file_get_contents($_FILES['upload']['tmp_name']);
if (!mb_check_encoding($content, 'UTF-8')) {
    throw new RuntimeException('上傳文件包含非法 UTF-8 序列');
}

3. 數據庫寫入前最後一道防線

<?php
function safeInsert(PDO $pdo, string $table, array $data)
{
    foreach ($data as $key => $val) {
        if (is_string($val) && !mb_check_encoding($val, 'UTF-8')) {
            throw new InvalidArgumentException("字段 $key 包含非法編碼");
        }
    }
    // 執行插入...
}

編碼檢查對照表

編碼名稱PHP 常量/字符串適用場景
UTF-8'UTF-8'現代 Web 應用默認編碼
GBK/GB2312'GBK'舊系統兼容、中文 Windows 環境
ISO-8859-1'ISO-8859-1'西歐語言、舊版 MySQL latin1
Big5'Big5'繁體中文舊系統

常見誤區提醒

  1. 以為 mb_check_encoding 能轉換編碼:它只驗證,不轉換。轉換請用 mb_convert_encoding() 或 iconv()。
  2. 忽略了請求級別的全量檢查:單檢查 $_POST['field'] 不夠,攻擊者可藏在 Cookie、Header、文件名等處。建議入口統一調用 mb_check_encoding(null, 'UTF-8')。
  3. 生產環境未開啟 mbstring:請確認 phpinfo() 中載入 mbstring 擴展,否則函數不存在。

總結

mb_check_encoding 是 PHP 內置的編碼安全閘門,代價極低(C 層實現)、覆蓋面廣。將其納入請求入口、文件處理、數據入庫等關鍵路徑,能以最小成本阻斷一類隱蔽且危險的編碼攻擊。配合 mb_internal_encoding('UTF-8') 統一內部編碼,構建乾淨可靠的字符處理環境。

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