php strlen遇0截断,聊下php下的截断问题
0x01 起因
有天在群里说起上传的%00截断的一些问题,就想起之前自己在这个问题踩过坑,想起了自己曾经的flag说要写文章,一直没写,现在来填坑了。
0x02 经过
源码理解1
2
3
4//test.php
include "1.txt\000.jpg";
?>
1
2
3
4//1.txt
echo 'helloworld';
?>
上面的示例代码在 php版本小于5.3.4 的情况下回输出 helloworld 。从php的内核执行过程来看,PHP通过 php_execute_script 来执行PHP的脚本,这里选取部分有关代码,具体可以看这里:
在 第10行 我们看到,他调用 zend_execute_scripts 来针对脚本进行解析,而这个函数是在Zend/zend.c里面,截取部分相关代码如下:
从PHP内核开来实际上是分为两块部分,一个是 compile编译过程 ,另一个是execute执行过程。
第一部分:compile编译过程
我们可以看到这里的代码逻辑通过 zend_compile_file 获取文件的内容,zend_compile_file是一个函数指针,其声明在/Zend/zend_compile.c中
1ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
在引擎初始化的时候,会将 compile_file 函数的地址赋值给 zend_compile_file 。
简单总结一下上面部分代码的逻辑:
zend_compile_file 函数首先调用 open_file_for_scanning 去读取文件,然后通过 第17行的zendparse 去进行语法和词法解析。而 zendparse 是通过 lex_scan 去扫描出token并进行语法分析。
第二部分:execute执行过程
zend_execute 也是一个函数指针,其声明在/Zend/zend_execute.h中。
1ZEND_API extern void (*zend_execute)(zend_op_array *op_array TSRMLS_DC);
在引擎初始化的时候,会将 execute 函数的地址赋值给 zend_execute 。
根据我们的了解,zend_execute 通过 ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER 函数来进行include的实际处理,即包含要包含的文件。
对比修复代码找到漏洞触发点:
摘出部分修复代码:
我看下存在漏洞的调试运行结果:
修复代码的 Z_STRVAL_P(inc_filename) 即上图中的val,即”1.txt”,strlen取得长度为5,而 Z_STRLEN_P(inc_filename) 即上图中的len即10。这里实际上解析到的文件名是1.txt。
不存在漏洞的调试运行结果:
一旦出现%00截断,include的文件名经过url转码由”1.txt%00.jpg”变为”1.txt\000.jpg”,进入php语法词法分析器解析后会将这个字符串解析成一个字符串,并使用 zend_scan_escape_string 进行字符串转码,如图,进入 zend_scan_escape_string 的内容为:
只要比较发现文件名的strlen长度和语法分析出来的长度不一样,就说明内部存在截断的字符,因此输出了打开文件失败的信息。
利用方式
划重点 PHP版本低于5.3.4
%00截断有这么2种利用状况
在burpsuite的16进制编辑工具将”shell.php .jpg”(带空格的)中间的空格由20改成00
在1中,url中的%00(形如%xx),web server会把它当作十六进制处理,然后将该十六进制数据hex(00)“翻译”成统一的ascii码值“NUL(null)”,实现了截断。
在2中,burpsuite用burp自带的十六进制编辑工具将”shell.php .jpg”(中间有空格)中的空格由20改成00,如果burp中有二进制编辑工具。
延伸一下
其实关于截断相关问题,还有个很有趣的函数, iconv() 函数:
在了解 iconv() 函数漏洞之前,可能需要一点前置知识
在php中,所有的字符都是二进制的串,PHP本身并不认识任何编码,只是根据编码来显示内容。PHP中的chr() 函数从指定的 ASCII 值返回字符。ASCII 值可被指定为十进制值、八进制值或十六进制值。八进制值被定义为带前置 0,而十六进制值被定义为带前置 0x。
而在php5.4之前, iconv() 函数在转换编码的时候,遇到不合法的字符串的时候会将其截断。
1
2
3
4
5
6
7<?php
for($k=0;$k<=255;$k++)
{
$a='shell.php'.chr($k)."1.jpg";
echo 'k:'.$k.' '.'$a:'.$a.' '.'iconv("UTF-8","gbk",$a):'.iconv("UTF-8","gbk",$a)."\n";
}
?>
通过fuzz发现,其中 iconv(“UTF-8”,”gbk”,$a) 或是 iconv(“UTF-8”,”gb2313”,$a) 都会在chr(128)到chr(255)之间截断,使结果为shell.php
在php5.4.0版本的时候就不存在这个问题了。
实际例子
关于我们刚刚说的 iconv() 截断的问题,其实sitestar pro就是个典型例子,我们看个例子:
漏洞触发点在 module/mod_tool.php 中的 img_create() 函数,截取部分代码如下:
这部分中有段代码吸引了我的注意力
1
2
3
4if(!preg_match('/\.('.PIC_ALLOW_EXT.')$/i', $file_info["name"])) {
Notice::set('mod_marquee/msg', __('File type error!'));
Content::redirect(Html::uriquery('mod_marquee', 'upload_img'));
}
跟进一下这个 PIC_ALLOW_EXT 参数,发现其在数据库中写死了,只允许 gif|jpg|png|bmp 这类文件。即如果文件名最后不是 gif|jpg|png|bmp ,则提示文件类型错误。
所以这部分的正则表达式的功能应该是针对文件后缀名进行检查。
继续跟进这部分代码,有一串代码如下:
1
2
3
4if (!$this->_savelinkimg($file_info)) {
Notice::set('mod_marquee/msg', __('Link image upload failed!'));
Content::redirect(Html::uriquery('mod_marquee', 'upload_img'));
}
这部分代码应该是进行文件保存的功能,这个有个核心函数 _savelinkimg ,跟进这个函数。
第二行问题出现了
1$struct_file['name'] = iconv("UTF-8", "gb2312", $struct_file['name']);
在 iconv 转码的过程中, utf->gb2312 (其他部分编码之间转换同样存在这个问题)会导致字符串被截断,如:$filename="shell.php(hex).jpg; (hex为0x80-0x99),经过 iconv 转码后会变成 $filename="shell.php" ;
0x03 结果
总结一下截断大概可以在以下情况适用
include(require)
file_get_contents
file_exists
所有url中参数可以用%00控制
0x04 参考文献
潜伏在PHP Manual背后的特性及漏洞(看雪峰会议题)
wooyun-2014-048293
php strlen遇0截断,聊下php下的截断问题相关推荐
- android studio 无法输入中文,Android Studio 升级到3.0后输入法中文状态下无法选词的终极解决方案...
AndroidStudio终于出3.0正式版了,内置了kotlin(虽然我安了插件一直能用).一直忍着没敢下rc版的好奇猫,总算装了正式版.当然,伴随每次大版本更新,总有一些恼人的后遗症,其中以gra ...
- oracle 日志 安全审计,等保测评2.0:Oracle安全审计(下)
1. 说明 本篇文章主要说一说Oracle数据库安全审计控制点中b.c.d测评项的相关内容和理解,以及一些其它零碎的与等保相关的内容. 2. 测评项 b)审计记录应包括事件的日期和时间.用户.事件类型 ...
- Creo4.0安装与VS2015环境下的开发配置
Creo4.0+VS2015 1. Creo4.0 M010下载地址 http://www.zh2013.com/post/20170627.html 建议使用迅雷下载 2. 安装Creo4.0 生成 ...
- .net framework 4.0 在 VS2010 安装目录下位置 dotNetFx40_Full_x86_x64.exe在磁盘哪个目录?...
.net framework 4.0 在 VS2010 安装目录下位置 dotNetFx40_Full_x86_x64.exe在磁盘哪个目录? 使用VS2010开发应用程序完毕后,在发布应用程序时,常 ...
- 痞子衡嵌入式:超级下载算法RT-UFL v1.0发布,附J-Link下安装教程
痞子衡主导的"学术"项目 <RT-UFL - 一个适用全平台i.MXRT的超级下载算法设计> 历时 8 个月终于迎来了 v1.0 版发布,因为是第一个正式版,为了保证质 ...
- 中安财报影像识别系统V2.0,为您摘下“紧箍咒
中安财报影像识别系统V2.0,为您摘下"紧箍咒 财务报表包含资产负债表.现金流表.利润表,是公司进行信贷审批.财务审计时的主要依据.财务报表核查,对于银行卡信贷审批.企业信用审核等行业的工作 ...
- 痞子衡嵌入式:超级下载算法RT-UFL v1.0在恩智浦MCUXpresso IDE下的使用
痞子衡主导的"学术"项目 <RT-UFL - 一个适用全平台i.MXRT的超级下载算法设计> v1.0 版发布近 4 个月了,部分客户已经在实际项目开发调试中用上了这个 ...
- strlen“好神奇”,永真式——if(strlen(q) - strlen(p) = 0)
今天突然发现神奇的一幕 这个if中居然是个永真式 怎么可能 char *p = "aaaaaaaa";char *q = "ssss";int x = strl ...
- Hadoop2.6.0+Linux Centos7+idea环境下:MapReduce二度好友推荐案例
目录 一.问题描述 二.intellij idea中编写代码+打包项目 三.xftp中上传jar包到Linux 四.hadoop中准备输入数据+运行jar包+查看输出结果 一.问题描述 使用MapRe ...
最新文章
- repeater实现删除按钮
- grep -v、-e、-E
- windows下mysql安装失败的一个解决案例
- python mysql批量更新_Python批量删除mysql中千万级大量数据的脚本分享
- Nginx与Zuul之间区别
- 校园管理系统需求分析文档
- SecureCRT内让npm进程后台执行不受关闭终端影响
- 第二章:React 面向组件编程
- 云际阔,总相连——Let's Connect!
- file对象怎么才会有值_怎么去聊天女生才会跟你约会
- excel运行python_使用PyXLL在Excel中执行Python脚本
- 正则表达式那些事儿(一)
- 如何根据纬度和经度获取城市名称
- excel输入 正在计算机,在Excel中输入内容后如何自动填写日期和时间
- 推荐测温软件SpeedFan 4.32
- 计算机打字在哪点,电脑打字在哪里打开
- npm install 报错 gyp info it worked if it ends with ok
- 抖音算法推荐机制详解!(科普向)
- 使用 Vite 插件自动化实现骨架屏
- 统计学基础——负二项分布的数字特征
热门文章
- Cloud一分钟 |高通预在年底与苹果和解;比特币绝地反弹;广电拿下5G,或成第四大运营商...
- HTML和css学术报告,清华大学 张超 副教授访问我院并做学术报告
- nginx绑定多个端口
- ElasticSearch 从安装开始_01
- docker sonarqube:7.7-community
- linux mysql5.7启动失败/tmp/mysql.sock ?
- maven打包时跳过测试
- 服务器上的文件怎么取名,给新的服务器取名你会取神马?
- 我的特长是计算机VF编程,2016计算机二级考试VF模拟题及答案
- 命令行编译java项目_命令行编译运行java工程(转)