0%

HITCON 2017 SSRFme

[HITCON 2017]SSRFme

buu上的一个老题,又是不会做看wp的一天

给了源码

<?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__);

remote_addr就是用来创建一个沙盒的,然后用shell_exec执行一个GET命令,escapeshellarg会转义所有引号再在整个参数上加一个引号,防止了命令注入,就是说只能执行GET。
这个GET就是一个GET请求,可以使用file协议什么的,通过Perl实现(是我不懂的东西)
整体效果就是把GET请求到的东西写入我们对应的沙盒文件夹中。本来想写直接写一个PHP的shell的,但是靶机不能访问外网,并且估计也设置了沙盒中的PHP文件都不能解析之类的限制,而写文件的路径也被控制在了沙盒内,跳目录什么的也不太行

GET的使用

GET 后面可以直接接目录获取目录信息,就等于ls,还有就是file协议读一些东西啦,可以扫一下根目录看到/readflag和/flag。flag自然是被设置了权限不能读,要通过执行/readflag来读取flag。

题解

有两种解法,一种是Perl对未知协议出现时会在试图加载对应名称的pm文件,如果我们在自己的服务器上放一个反弹shell脚本然后让他写入本地,再通过错误的协议让他加载,就可以实现getshell,文末链接中附有Perl反弹shell的脚本,但是buu上这个靶机好像不能访问外网,只得作罢

第二种解法是GET在实现时调用open函数的相关漏洞(我没看懂原理),但是利用方式即为file:filename,如果file协议访问的这个filename是cmd|的形式,那么就会执行这个cmd
后来出了一个补丁,需要filename存在时才可能执行到open那一步,但是刚好这里我们又可以创建任意名称的文件,从而任意命令执行

小坑

一开始想直接执行/readflag,试了半天没用,然后就用bash去执行,为了保险写了全路径/bin/bash,没想到还是不行,最后ls看了一下目录,发现斜杠/全都在处理文件名的时候被作为目录丢掉了,/readflag变成了readflag,自然就没法使用了,但是我就算是使用bash -c /readflag这里也会有一个斜杠出现,为什么又可以成功呢?
还有就是使用bash执行命令行命令的时候要用-c,指定其在命令行下运行,否则会尝试用bash去执行那个二进制文件,不会有结果(bash理论上就可以执行一下.sh脚本)