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

PHP 安全編程:Null 字節攻擊原理、利用與防禦最佳實踐

     編輯:PHP 綜合知識

PHP 底層基於 C 語言,字符串以 Null 字節 (\0) 結尾。若用戶輸入包含 Null 字節通過文件系統函數處理,可能繞過邏輯檢查,導致任意文件讀取/包含漏洞。

攻擊原理演示

<?php
// 易受攻擊代碼
$file = $_GET['file'];  // 用戶傳入: "../../etc/passwd\0"
if (file_exists('/home/wwwrun/' . $file . '.php')) {
    // file_exists 看到: /home/wwwrun/../../etc/passwd.php (實際: /etc/passwd)
    // 因為 C 函數在 \0 截斷,忽略後綴 .php
    include '/home/wwwrun/' . $file . '.php';
    // 實際包含: /etc/passwd
}
?>

漏洞利用場景

  • include/require:繞過後綴限制包含敏感文件
  • file_exists/is_file:繞過存在性檢查
  • fopen/file_get_contents:讀取任意文件
  • unlink/rename:刪除/重命名任意文件
  • move_uploaded_file:繞過上傳驗證

防禦最佳實踐

1. 輸入驗證:白名單機制(最推薦)

<?php
$file = $_GET['file'];
$allowed = ['home', 'about', 'contact', 'products'];

if (in_array($file, $allowed, true)) {
    include "/home/wwwrun/{$file}.php";
} else {
    include "/home/wwwrun/home.php";  // 默認頁面
}

2. 過濾 Null 字節

<?php
// PHP 5.3.4+ 內部函數已自動處理,但建議顯式過濾
$file = str_replace(chr(0), '', $_GET['file']);
// 或
$file = preg_replace('/\0+/', '', $_GET['file']);

// 通用過濾函數
function remove_null_bytes($input) {
    return is_array($input) 
        ? array_map('remove_null_bytes', $input) 
        : str_replace("\0", '', $input);
}

$_GET = remove_null_bytes($_GET);
$_POST = remove_null_bytes($_POST);
$_REQUEST = remove_null_bytes($_REQUEST);

3. 使用 realpath() 規範化路徑

<?php
$base = '/home/wwwrun/';
$requested = $base . $_GET['file'] . '.php';

// 獲取真實絕對路徑
$real = realpath($requested);

// 確保在基礎目錄內
if ($real && strpos($real, $base) === 0) {
    include $real;
} else {
    die('非法路徑');
}

錯誤信息洩露風險

詳細錯誤輸出可能洩露:

  • 數據庫結構、查詢語句
  • 文件系統路徑、權限
  • 代碼邏輯、框架版本
  • 服務器環境信息

三層錯誤處理策略

層級策略實現
開發環境顯示詳細錯誤error_reporting(E_ALL); ini_set('display_errors', 1);
測試/預發布記錄詳細日誌,頁面友好提示log_errors=On; display_errors=Off
生產環境記錄關鍵日誌,用戶見通用頁面自定義錯誤處理器 + 監控告警

自定義錯誤處理器示例

set_error_handler(function($severity, $message, $file, $line) {
    if (!(error_reporting() & $severity)) return false;
    
    $log = "[ERROR] $message in $file:$line\n";
    error_log($log, 3, '/var/log/php/app_errors.log');
    
    // 生產環境不輸出詳情
    if (ENV_PRODUCTION) {
        http_response_code(500);
        include 'templates/500.php';
        exit;
    }
    return false;  // 繼續標準處理
});

核心原則:永遠不信任外部輸入,採用白名單驗證,最小權限原則操作文件系統,分環境差異化錯誤處理。

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