0x01 概要

大概是26号晚上,Th1s师傅在群里发了个typecho有后门的消息,看到了以后就去搜了下,找到了一片分析的文章,大致的漏洞成因是在typecho安装成功后,并为自动删除install.php,但是在这个install.php中存在一个php的反序列化漏洞,并存在一个能够执行命令的利用方式。
该漏洞在24号就被修补上了,并且作者也在27号进行了回应,我选择相信作者,一是因为作者回应文章写的有理有据,二是因为我自己也做过开发,真心觉得支撑这样一个开源项目是相当不容易的。


0x02 源码分析

在得知这个漏洞的大概形成原因后,我没有仔细的看别人的分析文章,只是知道漏洞存在install.php这个文件中,是一个反序列化漏洞,那么就先打开install.php看一下哪里存在反序列化函数

在一堆html中间我发现了这堆代码,可以看到是对cookie中的__typecho_config进行的反序列化。
看到这里就想起了Th1s师傅总结的对于PHP反序列化能被利用所需要满足的两个条件:

在这里我们可以对cookie中的内容进行控制,接下来就需要找到POP链(Property-Oriented Programing)。
这里在反序列化后,使用$config['adapter']$config['prefix']new了一个新的DB对象,那么这个时候是会调用Typecho_Db这个对象的构造函数,进入到这个函数的构造函数中:

看到这里的时候,由于对于魔术方法的不熟悉,并没有看出哪里有可以利用的地方,但是看了王松_Striker关于typecho的“后门”分析,其中关于魔术方法的总结让我豁然开朗:

可以看到__toString这个魔术方法是在把类当作字符串的时候会触发的,这个时候我们再来看上面的代码,中间有一行可以看到:

在这里,将$adapterName当做了字符串拼接到了Typecho_Db_Adapter_后面,那么机会来了,这个$adapterName是前面我们传递过去的,也就是$config['adapter'],是我们完全可以控制的,所以接下来全局搜索__toString这个函数,会发现有两个类实现了这个魔术方法,Typecho_Db_QueryTypecho_Feed,第一个里面没有发现有用的东西,那么来看第二个,只截取关键部分:

第一遍看到这里的时候并没有发现有什么问题,但是再次仔细看了之后发现了有一行存在问题:

这里如果screenName如果是一个不可访问的属性的时候则会调用__get方法,但是在这个类中却没有实现__get方法,那么我们接下来再全局搜索__get方法,看看哪里存在:

跟进去看一下:

这个里面是一堆赋值的语句,并没有什么问题,跟进return后面的函数:

终于在这个函数里面看到了久违的希望–call_user_func,有了这个函数,我们就可以自己构造了,像执行什么函数就执行什么函数。


0x03 POC编写

分析过后只是把漏洞的原理讲清楚了,真正的利用还是另一码事,所以在编写POC的时候要一步一步来。
首先在进入漏洞之前需要满足几个条件,看源码说话:

这里说明要在利用的时候要设置referer,然后继续往下看:

这里说明要使用get传递个finish参数,并且__typecho_config这个里面有值(废话,当然有值了)。
然后在反序列化后,调用toString的时候,我们需要将传递过去的$config['adapter']变为Typecho_Feed这个类,这样才能调用__toString魔术方法。
最后,由于要使用到Request.php文件中的Typecho_Request类的__get魔术方法,我们还需要将构造的Typecho_Feed类中的$item['author']定义为Typecho_Request类。最后的最后,我们需要在定义好的Typecho_Request类中为定义两个变量:$_params$_filter,并且在类的构造函数中对其进行赋值。
至此,POC就结束了,我们对上述构造的类进行序列化,并base64_encode,然后放入cookie__typecho_config字段中,就可以了。
POC如下:

上述POC摘自王松_Striker的文章中。
成功截图:


0x04 相关链接

王松_Striker的分析文章
Th1s的分析文章
typecho作者回应
POP链介绍

Leave a Comment

电子邮件地址不会被公开。 必填项已用*标注