realpath() + 前缀校验是唯一可靠防线:先对根目录和用户路径分别调用realpath(),显式检查返回值是否为false,再用str_starts_with()或0===strpos()严格比对前缀,且校验必须在file_exists()之前完成。

PHP 8.5.5 本身不自动防路径遍历,必须靠你写对逻辑——realpath() + 前缀校验是唯一可靠组合,其他都是辅助或无效的。
realpath() 必须配合严格前缀比对,否则等于没做
很多人调用 realpath('./uploads/'.$user_input) 就以为安全了,但漏掉两个致命点:realpath() 对越权路径或不存在路径返回 false,而 strpos($full, $root) 在 $full === false 时会返回 false,再用 !== false 判断就误判为合法。
- 必须显式检查
$full === false,不能跳过 -
$root要用realpath('./uploads/')获取,且末尾带斜杠(/var/www/uploads/),否则/var/www/uploadsssh_key可能被strpos误匹配 - 比对必须用
str_starts_with($full, $root)(PHP 8.0+)或0 === strpos($full, $root),不能用!== false - 校验必须在
file_exists()或is_readable()之前完成,否则存在竞态条件
basename() 单独用根本挡不住,尤其遇到 urldecode() 漏洞
basename('../../etc/passwd%00.jpg') 返回 passwd%00.jpg,后续若用 pathinfo(..., PATHINFO_EXTENSION) 取扩展名,%00 后内容被截断,导致校验失效;更糟的是,某些旧环境或配置下,%00 会让 file_exists() 提前终止解析,绕过检查。
- 如果要用
basename(),必须先urldecode($user_input),再basename(),否则%2e%2e%2f这类编码完全绕过 -
basename()不处理符号链接、Unicode 全角点(.)、.//、.\.\等变体,仅适合内部已知安全路径的纯文件名提取 - 上传场景中,
$_FILES['file']['name']也得走同样流程:先urldecode(),再basename(),再白名单正则过滤(如/^[a-zA-Z0-9_.-]+$/)
上传和下载必须切断用户输入与物理路径的映射
把上传目录放在 public/ 下直出,等于给攻击者铺路;返回 /uploads/xxx.jpg 这种 URL 给前端下载,等于重开一个遍历入口。
- 上传根目录必须移出 Web 根目录,比如
runtime/uploads/,Nginx/Apache 默认不可直接访问 - 上传后必须用
finfo_open(FILEINFO_MIME_TYPE)校验真实 MIME,拒绝application/x-php、text/x-php等类型 - 文件名必须丢弃原始值,用
uniqid('up_').bin2hex(random_bytes(8)).'.jpg'重命名,扩展名由 MIME 映射决定,不取用户输入 - 下载必须走 PHP 控制器,用
readfile($real_path)输出,并设置Content-Disposition: attachment; filename="safe.pdf",其中filename用basename()处理,避免原始名含../
PHP 8.5.5 的变化不影响核心防御逻辑
PHP 8.5.5 是维护更新版,修复底层错误、加固安全机制,但它没改 realpath() 行为,也没禁用 %00 截断(现代 PHP 默认已禁,但别依赖),更没让 basename() 突然变安全。
- 别指望版本升级自动修复路径遍历——所有校验逻辑仍需你手写
- 老项目升级到 8.5.5 后,要确认
open_basedir、allow_url_include等配置仍关闭,这些才是运行时兜底 - 如果你用 ThinkPHP,注意它 5.1+ 的
input()和Request::param()返回原始字符串,不自动urldecode()或realpath(),拼路径前必须自己处理
最易被忽略的点:校验顺序。先 urldecode(),再 basename()(可选),再拼完整路径,再 realpath(),再前缀比对,最后才 file_exists() 或 is_readable()。少一步,就可能被绕过。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











