php防御目录遍历漏洞的核心是切断用户输入操控文件路径的能力,需严格校验路径参数、用basename()剥离路径、禁用点号序列、白名单限制字符、强制绝对路径并校验前缀、禁用动态包含而改用路由白名单、配合php.ini和web服务器加固。

PHP防御目录遍历漏洞,核心是切断攻击者通过用户输入操控文件路径的能力。关键不在“怎么写对”,而在“怎么拦住错的”——所有外部输入都必须经过验证、规范化和白名单约束,不能依赖一次过滤或侥幸心理。
严格校验并净化路径参数
任何来自 URL、表单、Cookie 或请求头的路径类参数(如 $_GET['file']、$_POST['dir'])都不能直接拼接进文件操作函数中。
- 用
basename()提取纯文件名,剥离所有路径成分:$filename = basename($_GET['file']); // 丢掉 ../../etc/passwd - 禁用点号序列:检查是否含
"."、".."、"%2e%2e"等编码或变体,可结合urldecode()+ 正则双重清理 - 白名单字符限制:只允许字母、数字、下划线、短横线等安全字符,例如:
$clean = preg_replace('/[^a-zA-Z0-9_\-]/', '', $input);
强制使用绝对路径并做范围校验
即使输入被净化,仍需确保最终路径落在预设的安全根目录内,防止符号链接逃逸或 realpath 绕过。
- 先拼接再解析:
$fullPath = realpath($safeRoot . '/' . $filename); - 严格比对前缀:
if ($fullPath === false || strpos($fullPath, $safeRoot) !== 0) { die('Access denied'); } - 避免仅用
str_starts_with(),因为/var/www/uploads可能被/var/www/uploadshack误判,必须用完整路径字符串开头匹配
禁用动态包含,改用路由白名单
像 include $_GET['page'] . '.php'; 这类写法是高危源头,应彻底废弃。
- 定义明确的可访问模块列表:
$allowed = ['dashboard', 'profile', 'settings']; - 从输入中提取后强制映射:
$page = in_array($clean, $allowed) ? $clean : 'home'; - 所有文件操作走固定路径,如
include "templates/{$page}.php";,不拼接用户值
服务端加固配合代码层防护
代码防护是第一道防线,但服务器配置能兜底。
- 在
php.ini中关闭危险选项:allow_url_include = Off<br>allow_url_fopen = Off
- 设置
open_basedir限定脚本只能访问指定目录树:open_basedir = "/var/www/site:/tmp" - Web服务器层面屏蔽敏感路径访问,例如 Nginx 中:
location ~ ^/(.git|\.ht|config\.php|logs/) { return 403; }
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











