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下的截断问题相关推荐

  1. android studio 无法输入中文,Android Studio 升级到3.0后输入法中文状态下无法选词的终极解决方案...

    AndroidStudio终于出3.0正式版了,内置了kotlin(虽然我安了插件一直能用).一直忍着没敢下rc版的好奇猫,总算装了正式版.当然,伴随每次大版本更新,总有一些恼人的后遗症,其中以gra ...

  2. oracle 日志 安全审计,等保测评2.0:Oracle安全审计(下)

    1. 说明 本篇文章主要说一说Oracle数据库安全审计控制点中b.c.d测评项的相关内容和理解,以及一些其它零碎的与等保相关的内容. 2. 测评项 b)审计记录应包括事件的日期和时间.用户.事件类型 ...

  3. Creo4.0安装与VS2015环境下的开发配置

    Creo4.0+VS2015 1. Creo4.0 M010下载地址 http://www.zh2013.com/post/20170627.html 建议使用迅雷下载 2. 安装Creo4.0 生成 ...

  4. .net framework 4.0 在 VS2010 安装目录下位置 dotNetFx40_Full_x86_x64.exe在磁盘哪个目录?...

    .net framework 4.0 在 VS2010 安装目录下位置 dotNetFx40_Full_x86_x64.exe在磁盘哪个目录? 使用VS2010开发应用程序完毕后,在发布应用程序时,常 ...

  5. 痞子衡嵌入式:超级下载算法RT-UFL v1.0发布,附J-Link下安装教程

    痞子衡主导的"学术"项目 <RT-UFL - 一个适用全平台i.MXRT的超级下载算法设计> 历时 8 个月终于迎来了 v1.0 版发布,因为是第一个正式版,为了保证质 ...

  6. 中安财报影像识别系统V2.0,为您摘下“紧箍咒

    中安财报影像识别系统V2.0,为您摘下"紧箍咒 财务报表包含资产负债表.现金流表.利润表,是公司进行信贷审批.财务审计时的主要依据.财务报表核查,对于银行卡信贷审批.企业信用审核等行业的工作 ...

  7. 痞子衡嵌入式:超级下载算法RT-UFL v1.0在恩智浦MCUXpresso IDE下的使用

    痞子衡主导的"学术"项目 <RT-UFL - 一个适用全平台i.MXRT的超级下载算法设计> v1.0 版发布近 4 个月了,部分客户已经在实际项目开发调试中用上了这个 ...

  8. strlen“好神奇”,永真式——if(strlen(q) - strlen(p) = 0)

    今天突然发现神奇的一幕 这个if中居然是个永真式 怎么可能 char *p = "aaaaaaaa";char *q = "ssss";int x = strl ...

  9. Hadoop2.6.0+Linux Centos7+idea环境下:MapReduce二度好友推荐案例

    目录 一.问题描述 二.intellij idea中编写代码+打包项目 三.xftp中上传jar包到Linux 四.hadoop中准备输入数据+运行jar包+查看输出结果 一.问题描述 使用MapRe ...

最新文章

  1. repeater实现删除按钮
  2. grep -v、-e、-E
  3. windows下mysql安装失败的一个解决案例
  4. python mysql批量更新_Python批量删除mysql中千万级大量数据的脚本分享
  5. Nginx与Zuul之间区别
  6. 校园管理系统需求分析文档
  7. SecureCRT内让npm进程后台执行不受关闭终端影响
  8. 第二章:React 面向组件编程
  9. 云际阔,总相连——Let's Connect!
  10. file对象怎么才会有值_怎么去聊天女生才会跟你约会
  11. excel运行python_使用PyXLL在Excel中执行Python脚本
  12. 正则表达式那些事儿(一)
  13. 如何根据纬度和经度获取城市名称
  14. excel输入 正在计算机,在Excel中输入内容后如何自动填写日期和时间
  15. 推荐测温软件SpeedFan 4.32
  16. 计算机打字在哪点,电脑打字在哪里打开
  17. npm install 报错 gyp info it worked if it ends with ok
  18. 抖音算法推荐机制详解!(科普向)
  19. 使用 Vite 插件自动化实现骨架屏
  20. 统计学基础——负二项分布的数字特征

热门文章

  1. Cloud一分钟 |高通预在年底与苹果和解;比特币绝地反弹;广电拿下5G,或成第四大运营商...
  2. HTML和css学术报告,清华大学 张超 副教授访问我院并做学术报告
  3. nginx绑定多个端口
  4. ElasticSearch 从安装开始_01
  5. docker sonarqube:7.7-community
  6. linux mysql5.7启动失败/tmp/mysql.sock ?
  7. maven打包时跳过测试
  8. 服务器上的文件怎么取名,给新的服务器取名你会取神马?
  9. 我的特长是计算机VF编程,2016计算机二级考试VF模拟题及答案
  10. 命令行编译java项目_命令行编译运行java工程(转)