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

Web 文件操作常見安全漏洞:目錄遍歷與空字節截斷攻擊

     編輯:PHP 相關知識

文件包含/讀取功能是 Web 應用高危區。本文剖析一個典型的不安全代碼,演示如何繞過 .. 替換與副檔名限制,並給出白名單防禦的最佳實踐。

脆弱代碼範例

<?php
$mod = isset($_GET['m']) ? trim($_GET['m']) : 'index';
$mod = str_replace("..", ".", $mod); // 嘗試過濾目錄遍歷
$file = "/home/www/blog/" . $mod . ".php";
@include($file);
?>

攻擊向量

攻擊者傳入:?m=...%2F...%2F...%2F...%2Fetc%2Fpasswd%00

  1. 繞過 str_replace:.../.../ 經替換後變為 ../../(雙重編碼/多層替換繞過)。
  2. 空字節截斷:%00 (URL 編碼的 NULL) 在 C 語言層面會截斷字串,導致 .php 後綴被忽略,最終包含 /etc/passwd。

為何過濾/替換不可靠

  • str_replace 只替換一次,多層嵌套可繞過(如 ....// → ../)。
  • 黑名單思維永遠跟不上繞過技巧(編碼、大小寫、雙重編碼、Unicode 正規化等)。
  • 同樣問題存在於 XSS 過濾(如 javascript 替換可被 jjavascriptavascript 繞過)。

正確防禦:白名單驗證

方法一:枚舉值白名單

$mod = isset($_GET['m']) ? trim($_GET['m']) : 'index';
$allowed = array('user', 'index', 'add', 'edit');
if (!in_array($mod, $allowed)) { exit('err!!!'); }

方法二:字元集白名單(正則)

$mod = isset($_GET['m']) ? trim($_GET['m']) : 'index';
if (!preg_match('/^\w+$/', $mod)) { exit('err!!!'); }

僅允許字母、數字、底線,徹底杜絕目錄遍歷、空字節、路徑分隔符等危險字元。

核心原則

  1. 已知即允許,未知即拒絕:白名單驗證輸入符合預期格式,而非嘗試過濾已知惡意模式。
  2. 參數化/預處理:資料庫查詢用預處理,檔案路徑用 basename() + 白名單,命令執行用 escapeshellarg()。
  3. 最小權限:Web 進程以低權限用戶運行,禁用不必要的 PHP 函數(exec, include 等)。

延伸建議

  • 升級 PHP 5.3.4+ 可免疫空字節截斷(%00 在檔案函數中不再生效)。
  • 使用 open_basedir 限制 PHP 可存取的目錄範圍。
  • 採用現代框架(Laravel, Symfony 等)內建的路由與視圖機制,避免手動拼接檔案路徑。

安全防禦的核心在於「簡單、嚴格、可驗證」的白名單邏輯,而非複雜易繞過的黑名單替換。

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