小说网站建设的支柱,常州网站设计公司,网盟推广图片,网站做icp备案有哪些好处0x01 起因有天在群里说起上传的%00截断的一些问题#xff0c;就想起之前自己在这个问题踩过坑#xff0c;想起了自己曾经的flag说要写文章#xff0c;一直没写#xff0c;现在来填坑了。0x02 经过源码理解1234//test.phpinclude 1.txt\000.jpg;?1234//1.t…0x01 起因有天在群里说起上传的%00截断的一些问题就想起之前自己在这个问题踩过坑想起了自己曾经的flag说要写文章一直没写现在来填坑了。0x02 经过源码理解1234//test.phpinclude 1.txt\000.jpg;?1234//1.txtecho 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() 函数在转换编码的时候遇到不合法的字符串的时候会将其截断。1234567?php for($k0;$k255;$k){$ashell.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() 函数截取部分代码如下这部分中有段代码吸引了我的注意力1234if(!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 ,则提示文件类型错误。所以这部分的正则表达式的功能应该是针对文件后缀名进行检查。继续跟进这部分代码有一串代码如下1234if (!$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 (其他部分编码之间转换同样存在这个问题)会导致字符串被截断如$filenameshell.php(hex).jpg; (hex为0x80-0x99)经过 iconv 转码后会变成 $filenameshell.php ;0x03 结果总结一下截断大概可以在以下情况适用include(require)file_get_contentsfile_exists所有url中参数可以用%00控制0x04 参考文献潜伏在PHP Manual背后的特性及漏洞(看雪峰会议题)wooyun-2014-048293