挖洞姿势 | 深度聊聊PHP下的“截断”问题
字数 1074 2025-08-18 11:37:28
PHP下的"截断"问题深度解析
0x00 前言
本文详细分析PHP环境下的截断问题,包括%00截断和iconv函数截断两种主要类型,适用于PHP安全研究人员和Web应用开发者。
0x01 %00截断原理
漏洞触发条件
- PHP版本低于5.3.4
- 涉及文件操作函数(include/require/file_get_contents等)
示例代码分析
// test.php
<?php include"1.txt\000.jpg"; ?>
// 1.txt
<?php echo 'helloworld'; ?>
在PHP<5.3.4环境下,上述代码会输出"helloworld",因为\000(空字符)截断了后续字符。
PHP内核执行过程
-
编译过程:
- 通过
zend_compile_file获取文件内容 - 使用
zendparse进行语法和词法解析 lex_scan扫描token
- 通过
-
执行过程:
zend_execute执行编译后的代码- 通过
ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER处理include操作
漏洞修复机制
PHP 5.3.4+版本中,当检测到文件名strlen长度与语法分析长度不一致时(存在截断字符),会输出"打开文件失败"。
0x02 %00截断利用方式
两种主要利用方式
-
URL中加入%00:
- 示例:
http://xxxx/shell.php%00.jpg - Web服务器将%00解码为ASCII NULL字符
- 示例:
-
BurpSuite十六进制编辑:
- 将"shell.php .jpg"中间空格(0x20)改为0x00
- 使用二进制编辑工具直接修改
受影响函数
- include/require
- file_get_contents
- file_exists
- 所有URL参数可控的场景
0x03 iconv函数截断
前置知识
- PHP中所有字符都是二进制串
chr()函数根据ASCII值返回字符- PHP5.4前,iconv遇到非法字符会截断
漏洞原理
$a = 'shell.php'.chr($k)."1.jpg";
iconv("UTF-8","gbk",$a); // 在chr(128)-chr(255)间会截断
实际案例(SiteStar Pro)
- 文件上传时检查后缀名正则:
if(!preg_match('/\.('.PIC_ALLOW_EXT.')$/i', $file_info["name"])) {
// 错误处理
}
- 漏洞触发点:
$struct_file['name'] = iconv("UTF-8", "gb2312", $struct_file['name']);
- 上传
shell.php{%80-%99}.jpg会被截断为shell.php
0x04 防御建议
- 升级PHP至5.3.4+版本
- 对用户输入进行严格过滤
- 避免直接使用用户提供的文件名进行文件操作
- 对iconv函数转换结果进行验证
- 实施白名单机制检查文件扩展名
0x05 总结
PHP截断问题主要分为两类:
- %00截断:影响PHP<5.3.4,通过空字符截断文件名
- iconv截断:影响PHP<5.4.0,编码转换时截断非法字符
理解这些漏洞原理有助于开发更安全的PHP应用,并有效防御相关攻击。