CVE-2016-5734 phpMyAdmin认证用户远程代码执行漏洞分析
0x00 前言
CVE-2016-5734在exploit-db上也就是 phpMyAdmin 4.6.2 - Authenticated Remote Code Execution ,意即phpMyAdmin认证用户的远程代码执行,根据描述可知受影响的phpMyAdmin所有的 4.6.x 版本(直至 4.6.3),4.4.x 版本(直至 4.4.15.7),和 4.0.x 版本(直至 4.0.10.16)。 CVE的作者利用在php 5.4.7之前的版本中preg_replace
函数对空字节的错误处理Bug,使注入的代码可远程执行。本文将会对此CVE进行相关分析。
0x01 环境搭建
init
在这里我会使用LAMP进行漏洞的调试和复现,首先在VirtualBox上安装Ubuntu 14.04 Server,安装成功后我们替换一下apt的源方便之后环境的安装与下载,命令如下:
apache
紧接着我们apt安装apache
mysql
再安装mysql
php
最后来啃啃php。由于php Bug的报告者使用的是php 5.4.0版本,我们就也安装5.4.0版本进行测试,apt-get
直接安装肯定是不行了,我们就下载源码进行安装吧,首先安装一下必要的编译环境
再安装在编译过程中对应选项所需要的库(你也可以根据自己的需求进行选择)
然后我们就来下载源码进行编译吧
可是在编译过程当中出现了make: *** [ext/dom/node.lo] Error 1
的错误,在github上也有人给了解决方案
至此编译的过程已经完成,这里还需要配置一下apache来解析php。在/etc/apache2/apache2.conf
的最后加上AddHandler application/x-httpd-php .php
,然后sudo service apache restart
重启apache,查看是否能够解析php
0x02 核心剖析
我们LAMP的环境搭建好了,让我们来看看这个PHP版本的Bug是怎么一回事。漏洞描述中有说php是在5.4.7中修复了该Bug,我们可以在php的changelog中查找其修复的Bug,据此定位到和该CVE相关的#55856 preg_replace should fail on trailing garbage问题。
在php代码中,和mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
函数相关的代码执行漏洞通常是使用了e修饰符,我们的demo如下:
在preg_replace
函数当中,加了e修饰符之后,在subject中匹配到pattern后会执行replacement中的代码,将执行结果进行替换,我们这里可以使用php的system
函数,可以直接输出命令执行的结果,如图
如果我们的demo变成了如下的代码,还会有漏洞吗
55856这个Bug就在这里发挥了作用,当php版本小于5.4.7时,可以向pattern中注入空字符产生截断,并传入e修饰符,使得我们可控的replacement代码执行,如图
0x03 漏洞分析
exploit-db中提供的Vulnerable App是phpMyAdmin 4.6.2,下载下来直接解压后访问的结果如下
在/libraries/common.inc.php的57行也可以知道4.6.x的版本要求php的版本是要大于5.5.0的
而在phpMyAdmin 4.4.15.6中则要求php版本大于5.3.0即可,我们就下载4.4.15.6版本的进行分析测试
根据exp我们可以知道此脚本利用的要求有两点
- 知道phpMyAdmin的路径,并且可以使用账号密码登录成功
- 知道对应db的table,或者在db中有创建table的权限
其次,在exp的以下代码中我们能够知道漏洞的触发点在于tbl_find_replace.php脚本中
tbl_find_replace.php的24行中,将POST的find
和replaceWwith
传入到了$table_search
的getReplacePreview
方法中
$table_search
是PMA_TableSearch
对象实例化的结果,而PMA_TableSearch
在libraries/TableSearch.class.php
中进行了定义,我们定位到libraries/TableSearch.class.php
的1430行
在getReplacePreview
方法中,由于exp中设定了$useRegex
的值,所以参数继续传递到_getRegexReplaceRows
方法中,定位到1388行
在1408~1413行当中,preg_replace("/" . $find . "/", $replaceWith, $row[0]);
很经典地还原了55856 Bug的场景,exp中通过 "find": "0/e\0","replaceWith": payload,
的POST提交,空字节截断并传入e修饰符进而执行我们的payload,也将替换的结果进行了回传,最终的复现如下
0x04 总结
个人感觉此CVE的利用还是有些版本和用户信息的要求,漏洞环境的搭建虽然有些小坑,但是根据exp逆向追踪漏洞根源的过程比较简单,在php Bug下所造成的漏洞还需要多积累相关经验去实践去挖掘