三个白帽之火币网2W大挑战
0x00 前言
L.N.师傅的这道题有点厉害,神奇的上传漏洞和有趣的Get Shell思路让人脑洞小开,从中学习到了很多有趣的东西特此小记。
由于第一集没有做出来,所以这次玩的是续集: [续集]火币网2W大挑战
1 | 由于乌云大会上无人解出此题,继续放出等待,有缘人获取火币网赞助价值2w人民币的比特币。 |
两个Tips,一个是读取源码的,另一个是绕过<?php die();?>
拿Shell的。
0x01 前期准备
首先来一发扫描目录
1 | [17:41:36] 403 - 313B - /cgi-bin/ |
从中得知有phpinfo.php
这个文件,于是乎访问phpinfo.php之。
得到了一个重要信息PHP Version 5.2.18-dev
,这个PHP版本很老,结合Tips可知旧版本上传安全检查不严导致的漏洞产生。
0x02 上传之读取源码
这个神奇的上传洞,大致原理就是低版本php上传部分对数组没有严格校验有安全漏洞,导致构造恶意数组会使上传内容错乱(在此则是上传的内容变成我们读取的文件的内容)。
这个地方有两个套路,一个是程序自身带有输出文件内容导致源码泄露(局限较大);另一个则是漏洞会把我们要读取文件的内容变成我们上传的内容,写到txt文件后就可读取源码了(知道上传路径即可获取源码)。
我们发现上传完一个文件后,底部会输出我们文件内容的base64加密后的密文,于是我们的套路一在此可用。
构造缺陷数组,进行攻击。
结果在返回的数据,可以看到我们可以读取index.php的内容,这就是套路一,成功获得了整站源码。
套路二
在进一步测试之后,发现点击完下载作业,把我们上传的代码转存到本地的时候,访问upload/b3.txt
看到了有趣的一幕。
PHP内部发生了奇妙的变化,使得上传的内容被替换成了目标文件index.php
的源代码,这就是套路二。
获取完源代码之后开始尝试利用Tips2获得Shell。
0x03 二次解密显真容
经过我们仔细研究,发现了一个可控的点做一些羞羞的事情。
1 | if(isset($_GET['download']) and isset($_GET['filename'])) |
这部分代码中,我们见到file_put_contents
函数,又发现$filename
是可控的,结合phpinfo
中支持php伪协议
,我们可以利用php伪协议搞事情。
于是乎,根据L.N.师傅的提醒,我们Get Shell的大致思路就出来了。
上传\n\r[换行符]base64_encode(shell)
->点击下载作业,把base64_encode(shell)
写到upload/davex.php
->php伪协议base64_decode(die + base64_encode(shell)
这样子die就变成了乱码,后面的shell就显示出来真容。
我们开始上传:
1 | upload/davex.php |
我们再上传一次shell,然后利用可控的$filename
,我们使用php伪协议操作文件,把upload/davex.php
解密一次。
1 | payload = php://filter/write=convert.base64-decode/resource=upload/davex.php |
(前面的乱码就是<?php die();?>,忽略运营商劫持插入的js文件)
这部分的原理我和Veneno师傅和Aklis师傅研究了一个晚上,实验之后了解了这个协议和这个函数的大致用法。
我们上传两个文件,一个是shell.txt(里面是\n\r[换行符]base64_encode(shell)
),一个是blank.php(空文件)。
1 | payload: index.php?download=[shell.txt id]&filename=php://filter/write=convert.base64-decode/resource=upload/blank.php |
也就是说覆盖blank.php
,其内容是shell.txt
的内容base64_decode,于是乎我们的blank.php被覆盖成我们的shell了。
这次的题目让人大开眼界,尤其是0x01的利用,感谢挑战者联盟
中的师傅们的帮助,也感谢L.N.师傅和三个白帽让大家有一个开脑洞的机会。