这段时间 Typecho 在十几天之内连续爆了两个最高可 getshell 的洞,先是 SSRF 可打内网,再是反序列化直接前台 getshell ……安全性这方面堪忧……
跟着师傅们的文章,简单地分析一下这两次漏洞,第二个反序列化的洞的溯源思路值得学习一波~
虽然很多大号都分析过这个漏洞,写的也很详细,我作为一个初学者自己分析学习一下也是很有必要的,官方人员已经对这些漏洞进行的及时的修补并且推出了最新的版本,如果有用到这个博客的同学赶紧升级。
Typecho 1.0 (14.10.10) —— SSRF 可打内网
0x01 漏洞原理
首先是显示了 “源地址服务器错误” 的报错,经过全局搜索发现报错是位于 var/Widget/XmlRpc.php
的 2046 行的 pingbackPing 函数
![](https://img-blog.csdnimg.cn/img_convert/3d35f413575babc87c3b9e2410d3f5e1.png)
调用了 get 方法,如果失败则返回 “源地址服务器错误” 的报错,我们跟进 get 方法看一下,大致意思是调用实例化 var/Typecho/Http/Adapter/
目录下的 Typecho_Http_Client_Adapter_Curl
类和 Typecho_Http_Client_Adapter_Socket
类,分别位于 Curl.php 和 Socket.php 文件中。如果 Curl 存在就使用 Curl 的 curl_setopt 函数打开资源,否则使用 Socket 的 fsockopen 函数打开资源,这两种方式都是打开资源的一种方式?
一般来说 Curl 都是存在的,所以我们继续回到 var/Widget/XmlRpc.php
的 2046 行的 pingbackPing 函数,向下看:
$http->setTimeout(5)->send($source);
直接在 Curl.php 和 Sockt.php 中是找不到 send 函数的, send 函数是在这两个类继承的 Typecho_Http_Client_Adapter
类中在 var/Typecho/Http/Client/Adapter.php
中的第 300 行可以看到 send 函数:
第 338 行,$response = $this->httpSend($url);
调用了本类的 httpSend 函数,转向 var/Typecho/Http/Client/Adapter/Curl.php
中第 41 行开始,一直到 51 行,都没有对传入的 url 进行检测,到 51 行后:
于是一个 SSRF 漏洞产生了
0x02 漏洞利用
这里还是跟着 JoyChou 表哥的思路
我们先看一下业务的逻辑,位于 var/Widget/XmlRpc.php
的 2046 行的 pingbackPing 函数:
![](https://img-blog.csdnimg.cn/img_convert/4eae879eec62699ebec7ee53e6cacb0a.png)
如果实例化类失败,返回 '源地址服务器错误',如果探测成功,并且返回码为 200 则返回 '源地址不支持 PingBack ' ,如果探测成功,但返回码不是 200 ,则返回 '源地址服务器错误'
所以我们探测端口主要就是通过返回码 200 这个地方。
利用一:端口检测
根据回显的不同,检测端口是否开启
payload:
curl "https://目标IP/action/xmlrpc" -d '<methodCall><methodName>pingback.ping</methodName><params><param><value><string>http://127.0.0.1:2222</string></value></param><param><value><string>joychou</string></value></param></params></methodCall>'
如果端口开启,则返回 “源地址不支持 PingBack ” ,如果端口没有开启,则返回 “源地址服务器错误”
利用二:攻击Redis
利用 Redis 默认空密码的特性,直接打内网,一般大站才会用 Redis
Typecho20171013前台 Getshell
一处反序列化导致的任意函数执行(可以执行代码和命令),据说是后门,因为找不到这出反序列化的用处
0x01 测试环境
Typecho-1.1-15.5.12-bete
PHP-5.5.9
Apache 2.4.7
Ubuntu
0x02 漏洞原理
这是一个反序列化的漏洞
先引用 Th1s 师傅的一段话:
反序列化漏洞的利用有两个条件:
① 进行反序列化的字符串可控
② 有可利用的pop链
首先看反序列化的可控字符串来源
发生在程序根目录下 install.php 的第 229 行
很突兀的一端代码(这也是被认为是后门的原因),直接接收 cookie 里的 __config 参数,然后进行 base64 解码进行反序列化
同时我们需要满足一些条件才可以控制数据,在 59 - 77 行
即传入 get 的 finish ,令 finish=1 即可,然后传入 Referer 为同源的地址
接下来寻找可利用的 pop 链
敏感的魔术方法(当满足某些条件时会自动调用)有:
![](https://img-blog.csdnimg.cn/img_convert/2212dbbf84937b3411667e2223b07a98.png)
进行全局搜索,发现在 var/Typecho/Db.php
中 Typecho_Db 类的第 120 行,__construct 方法中
$adapterName = 'Typecho_Db_Adapter_' . $adapterName;
存在拼接,那如果传入的 $adapterName 为对象的话就会调用 __toString 魔术方法,所以现在寻找有哪些类实现了 __toString 方法,并可以利用。可以用法师的代码审计工具,或者 Sublime 进行全局搜索关键字 __toString 。
在 var/Typecho/Feed.php
中的 Typecho_Feed 类中实现了 __toString 方法
在290行:
$content .= 'dc:creator' . htmlspecialchars($item['author']->screenName) . '/dc:creator' . self::EOL;
__get方法会在调用私有属性的时候自动执行,如果 $item['author'] 是一个对象,则访问它的 screenName 属性,这个时候要注意,如果screenName 是 $item['author'] 代表的类中的私有属性,那么就会调用 __get方法;
接下来全局搜索 __get 方法
在 var/Typecho/Request.php
中 Typecho_Request 类的 __get 方法如下:
226 行
跟进到 295 行
跟进 $this->_applyFilter($value)
到 159 行
其中有一个 call_user_func($filter, $value);
就可以执行任意函数了
0x02 漏洞利用
看了很多 POC,发现 Th1s 师傅的思路是最精简的,仿照思路,自己写了一个:
![](https://img-blog.csdnimg.cn/img_convert/ea50d8efc25ac285e6c0cac7b5d8e807.png)
将生成的 payload 复制下来
然后直接访问:
http://【被攻击的网站】/install.php?finish=1
抓包添加:
Referer: http://45.32.90.22:666/admin/
添加 cookie 中 __typecho_config=【payload】
发过去,就能成功写 shell 了
回显 500 是因为反序列化执行完毕之后,再执行到后面参数不符合DB方法中要求,所以报 500 ,但木马已经写入
![](https://img-blog.csdnimg.cn/img_convert/699ee4fef7668d32a024d50187bba6a1.png)
如果我们想让数据回显呢?也是有办法的,在反序列化之前执行了 ob_start ,开启了缓存区,而在反序列化之后把缓存区清零了,也就没有了输出;然而,如果我们在反序列化的过程中让 php 报错,就会终止脚本的执行,然后直接将缓存区的东西输出出来,这一点 LR 师傅的文章:
https://paper.tuisec.win/detail/68ea208985e5c7a.jsp
写的很详细,调用了不存在的 ['name'] 导致报错,然后把 payload 中的 phpinfo() 信息爆了出来.
0x03 漏洞复现
已经在我的 DockerHub 仓库:
https://hub.docker.com/r/ph0rse/typecho_17_10/)
中发布了,欢迎来 pull ,使用说明在仓库界面。