CVE-2016-5734 phpmyAdmin代码执行漏洞分析

首页 / 技术分享 / 正文

0x00 phpmyAdmin介绍

phpMyAdmin 是一个以PHP为基础,以Web-Base方式架构在网站主机上的MySQL的数据库管理工具,让管理者可用Web接口管理MySQL数据库。借由此Web接口可以成为一个简易方式输入繁杂SQL语法的较佳途径,尤其要处理大量资料的汇入及汇出更为方便。其中一个更大的优势在于由于phpMyAdmin跟其他PHP程式一样在网页服务器上执行,但是您可以在任何地方使用这些程式产生的HTML页面,也就是于远端管理MySQL数据库,方便的建立、修改、删除数据库及资料表。也可借由phpMyAdmin建立常用的php语法,方便编写网页时所需要的sql语法正确性。

0x01 漏洞描述

phpmyAdmin中的preg_replace函数在执行按照正则表达式替换字符串时,依靠/e修饰符可以执行任意php代码,具体原理参考我的这一篇文章
PHP中preg_replace函数代码执行特性

0x02 影响版本

php版本:4.3.0 -> 5.4.6
phpmyAdmin版本:
4.0.0 -> 4.0.10.16版本
4.4.0 -> 4.4.15.7版本
4.6.0 -> 4.6.3版本

0x03 漏洞分析

前提:后台权限;有账号密码。
首先根据官方发布的信息来看,触发点在libraries目录下的TableSearch.class.php文件内,位于_getRegexReplaceRows函数中,我们找到位置如下
请输入图片描述

可以看到,preg_replace函数用到了三个参数,分别是:$find、$replaceWith和$row[0],我们依次对他们进行溯源
首先对_getRegplaceRows函数进行溯源,发现同文件下的getReplacePreview函数调用了_getRegexReplaceRows,并且传递的参数为:$columnIndex, $find, $replaceWith, $useRegex, $charSet
请输入图片描述

再继续跟踪getReplacePreview,发现是主目录下的tbl_find_replace.php文件调用了getReplacePreview方法;
首先判断是否存在post参数$find,如果存在则接收post参数:$columnIndex,$find,$replaceWith,$useRegex,其中$find,$replaceWith为触发点需要用到的两个参数
请输入图片描述

preg_replace函数所需要用到的两个可控post参数溯源完毕,我们再来溯源一下刚刚提到的第三个参数$row[0],明显可以看出是一个数组的第一个元素;
从下面的图可以看到,$row数组的内容为$result通过foreach进行循环赋值给$index=>$row
那么$result的内容呢,可以看到是通过$sql_query从数据库中获取的
请输入图片描述

我们再来看一下$sql_query的内容
请输入图片描述

将累加的内容加上后,可以将其等效于如下sql语句

select $column ,1,cont(*) from db.tb where $column rLike '$find' collate $charset_bin group by $column order by $column ASC;

这个语句在PMA_TableSearch类中,发现在tbl_find_replace.php文件中new了一下PMA_TableSearch,初始化了$db, $table两个参数
请输入图片描述
请输入图片描述

我们再次跟踪这两个参数,发现在libraries目录下的common.inc.php文件直接定义了这两个参数

tbl_find_replace.php文件中包含了common.inc.phpTableSearch.class.php,我们在TableSearch.class.php找到$db, $table

刚刚提到的$sql_query查询语句,是将查询到的$result的第一个值给了preg_replace用到的第三个参数$row[0]
至此,preg_replace用到的三个参数全部溯源完毕,那么我们要怎么利用呢?

让我们回到触发点

preg_replace(
     "/" . $find . "/",
     $replaceWith,
     $row[0]
);

我们需要执行php的代码,就需要让它获取到的内容变成类似这样

preg_replace(
     "/test/e",
     "phpinfo();",
     "test"
);

我们浏览器访问触发点的页面http://localhost/tbl_find_replace.php,发现是一个查找替换数据库内容的功能页面;
通过前端分析我们可以发现,$find$replaceWith都可以直接通过post直接传递;
$find要变成/test/e可以通过%00将后面的“/”截断,$replace是要执行的php代码

第三个参数$row[0],经过对刚刚sql语句的分析,获取到的内容为指定数据库的指定数据表内的第一个字段值,可以通过后台手动构建数据表结构,达到让$row[0]获取的内容为匹配$find正则表达式的效果

0x04 修复建议

升级phpmyAdmin版本
或升级php版本

打赏
评论区
头像
文章目录