2017HITCON-CTF-SSRFMe
代码审计
拿到题意直接给出了源码如下:
1 |
|
审计分析源码过程大致如下:
- 进入
./sandbox/sandbox
目录 - 执行GET命令,GET的内容可控
- 将内容写入
./sandbox/sandbox/filename
- 最终直接访问
./sandbox/sandbox/filename
可以获取到GET执行获得的内容
GET初利用
首先利用SSRF我们可以传入url=file:///&filename=456
获得根目录的文件路径列表,访问/sandbox/sandbox/456
发现readflag和flag
可是当我们想读取flag和readflag的时候,发现flag无法直接读取出来,readflag读取并下载出来发现ELF文件头,是一个可执行文件,猜测需要执行readflag这个文件才能获得flag。(猜测这个文件本身有可执行权限)
于是我们需要执行命令运行这个可执行文件。
GET执行任意命令
这里利用的是比较早就被爆出来的一个问题。这里的原理涉及到代码的底层实现,不过多深究,来自LoRexxar师傅的文章:
1 | root@iZ285ei82c1Z:~/test# cat a.pl |
而perl里的GET函数底层就是调用了open处理
1 | file.pm |
open函数本身还支持file协议
1 | root@iZ285ei82c1Z:~/test# cat /usr/share/perl5/LWP.pm |
综合看起来是把一个文件名拼接入命令导致的命令执行。
(同理,我们对GET命令而言,通过传入命令文件名和命令来执行)
这里补充一点
perl在open中可以执行命令,格式有两种:
open(FD, "ls|")或open(FD, "|ls")
利用方式
1 | GET file:ls| |
这里我在kali虚拟机里测试了一下,发现只有 file:|id
有效。但是参考网上wp,其中都是采用的 file:id|
的方式
于是我又在vps上测试了一下
可以发现在vps下两种方式都是可行的,这里可能跟perl版本有关,具体原因有点迷。那么我们对题目进行测试的话两种都试一下。
Linux 执行文件
首先必须要知道,对于一个可执行文件(Linux下具有”x”属性的文件),我们要执行这个文件(换句话来说就好比运行Windows下的exe文件)。
Linux下,如果文件是可执行文件,或者是脚本文件,只要有可执行权限就可以直接执行,操作命令如下:
./filename
在当前路径下对执行filename文件
绝对路径
直接给出可执行文件的绝对路径并回车
回来看我们的题,我们现在需要做的是执行根目录下的readflag,并且把readflag的内容写入某个文件,最后我们再访问该文件即可得到readflag执行后得到的结果。
payload
?url=&filename=|/readflag
创建与命令同名文件
?url=file:|/readflag&filename=123
执行命令
/sandbox/sandbox/123
访问执行结果
同时也试了另外一种(管道符在右边),并没有读出结果。看了网上的大多数复现,发现都是采用的管道符在右边这种形式,并且是以bash -c {命令}
整体作为命令执行的
来自网上提供的解:
/?url=file:bash -c /readflag|&filename=bash -c /readflag|
创建相应的同名文件/?url=file:bash -c /readflag|&filename=123
利用open的feature执行代码
最后直接访问/sandbox/sandbox/123就能得到flag