You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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没有内置的直接检测路径是否越界的函数,但可以通过解析真实路径并对比前缀的方式实现需求:

核心逻辑

  1. 定义允许访问的根目录(如DIR_2的绝对路径)
  2. 将用户传入的相对路径拼接为完整路径,用realpath()解析出真实绝对路径(自动处理../、./等相对符号)
  3. 检查真实路径是否以允许的根目录为前缀,以此判定是否越权

代码实现

<?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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 15:05:26