PHP中如何检测文件/目录路径是否超出指定目录范围?
PHP 8.0 路径遍历安全检测实现
问题背景
网站目录结构如下:
website home (httpdocs) |_file_1 |_file_2 | |_DIR_1 | |_file_3 | |_file_4 | |_DIR_2 | |_something.php | |_file_5 | |_public |_index.php
仅允许公开访问DIR_2下的文件,用户通过/DIR_2/something.php?get_file=file_5可合法请求文件,但传入?get_file=../DIR_1/file_3时,会触发无限制的跨目录访问,存在路径遍历安全风险。需要实现逻辑判断用户指定的文件路径是否超出允许的目录范围。
实现方案
PHP没有内置的直接检测路径是否越界的函数,但可以通过解析真实路径并对比前缀的方式实现需求:
核心逻辑
- 定义允许访问的根目录(如
DIR_2的绝对路径) - 将用户传入的相对路径拼接为完整路径,用
realpath()解析出真实绝对路径(自动处理../、./等相对符号) - 检查真实路径是否以允许的根目录为前缀,以此判定是否越权
代码实现
<?php // 允许访问的目标目录(__DIR__对应当前脚本所在的DIR_2路径) $allowedDir = realpath(__DIR__); // 获取用户传入的文件路径,默认空值做容错 $userFilePath = $_GET['get_file'] ?? ''; /** * 判断文件路径是否超出允许目录 * @param string $allowedDir 允许访问的根目录绝对路径 * @param string $userFilePath 用户传入的文件路径 * @return bool true=超出范围,false=在允许范围内 */ function isFileOutsideAllowedDir(string $allowedDir, string $userFilePath): bool { // 拼接完整路径并解析真实路径 $fullFilePath = realpath($allowedDir . DIRECTORY_SEPARATOR . $userFilePath); // 路径解析失败(文件不存在或非法)直接判定为越权 if (!$fullFilePath) { return true; } // 检查真实路径是否以允许目录为前缀 return !str_starts_with($fullFilePath, $allowedDir); } // 执行检测 if (isFileOutsideAllowedDir($allowedDir, $userFilePath)) { echo "文件路径非法,超出允许访问范围"; // 可添加日志记录、终止请求等后续处理 exit; } else { echo "文件路径合法,可继续处理"; // 后续执行文件读取等业务逻辑 }
关键细节
realpath():必须使用,它会将所有相对路径符号解析为真实绝对路径,彻底避免路径绕过str_starts_with():PHP 8.0原生支持,简洁高效地判断路径前缀,比字符串截取更安全- 容错处理:若路径解析失败(如文件不存在)直接判定为非法,避免恶意构造的无效路径
额外防护建议
- 永远不要信任用户输入的路径参数,必须做严格校验
- 可结合
basename()限制仅能访问文件,禁止直接遍历目录 - 确保
allowedDir为绝对路径,避免相对路径导致的检测失效
内容的提问来源于stack exchange,提问作者GWS
相关产品推荐
相关产品推荐

