PHP空字节截断漏洞源于多层解析不一致:过滤层未截断%00、解码层还原\x00、执行层按C字符串截断。需通过上传文件名(如shell.php%00.jpg)、包含路径(如?page=header.php%00.jpg)、旧版PHP(<5.3.4)及函数行为(pathinfo、strlen等)综合验证。

检测 PHP 空字节截断漏洞,核心是验证目标系统在文件操作、路径解析或参数处理环节是否对 %00(即 \x00)存在“多层解析不一致”——也就是过滤层没截断、解码层还原了空字符、执行层却按 C 风格字符串提前终止。这不是靠扫描器一扫就能确认的,需要结合行为观察与针对性试探。
从上传功能入手验证
文件上传是最常见触发点。构造一个带空字节的文件名(如 shell.php%00.jpg),上传后抓包修改,并确保服务器实际接收的是 URL 解码后的 shell.php\x00.jpg:
- 用 Burp Suite 或浏览器开发者工具拦截上传请求,在 filename 字段填入
test.php%00.png,再手动对%00执行 URL 解码(变为\x00)后放行 - 观察响应:若返回成功但文件被保存为
test.php(而非完整名字),说明底层函数(如move_uploaded_file)已截断 - 进一步访问该文件(如
/uploads/test.php),看是否能解析执行 PHP 代码——能执行即确认漏洞存在
检查包含类逻辑中的路径控制
当页面存在 include、require 或模板加载且参数可控(如 ?page=header)时,尝试注入空字节绕过白名单限制:
- 先确认基础过滤:访问
?page=../../etc/passwd看是否报错或读取失败,建立基线 - 再试
?page=header.php%00.jpg,注意观察响应变化——如果原本被拦截的非法后缀(如.jpg)突然“生效”,而实际包含的却是header.php,就是典型截断表现 - 配合
php://filter协议一起测试,例如?page=php://filter/read=convert.base64-encode/resource=conf.php%00.jpg,看能否成功读取源码
关注旧版本 PHP 与特定配置组合
PHP 5.3.4 之前版本、未禁用 magic_quotes_gpc 或启用了宽松路径解析的环境更容易暴露该问题:
立即学习“PHP免费学习笔记(深入)”;
- 查看响应头或错误信息中是否泄露 PHP 版本;若低于 5.3.4,需重点排查
pathinfo()、basename()、dirname()等函数的使用场景 - 测试
$_GET参数在经过pathinfo()处理后是否被截断:发送?f=index.php%00.css,打印pathinfo($_GET['f'], PATHINFO_EXTENSION)的结果,若输出为空或php而非css,说明已被截断 - 检查 php.ini 中
allow_url_include=On是否开启——这会放大空字节在远程包含中的危害
用简单脚本辅助判断
在可控测试环境中,可部署一段诊断代码快速验证底层行为:
- 新建
test_null.php,内容为:<?php var_dump($_GET['a']); echo strlen($_GET['a']); ?> - 访问
test_null.php?a=abc%00def,观察输出:若var_dump显示完整字符串但strlen返回 3,说明内部存储含\x00且长度计算受其影响 - 再调用
file_exists('test.php%00.txt')或include 'test.php%00.txt',看是否等效于操作test.php



















