phpMyAdmin是一套开源的、基于Web的MySQL数据库管理工具。在其查找并替换字符串功能中,将用户输入的信息拼接进preg_replace函数第一个参数中。
在PHP5.4.7以前,preg_replace的第一个参数可以利用\0进行截断,并将正则模式修改为e。众所周知,e模式的正则支持执行代码,此时将可构造一个任意代码执行漏洞。
以下版本受到影响:
4.0.10.16之前4.0.x版本
4.4.15.7之前4.4.x版本
4.6.3之前4.6.x版本(实际上由于该版本要求PHP5.5+,所以无法复现本漏洞)
漏洞的原理
preg_replace漏洞触发有两个前提:
01:第一个参数需要e标识符,有了它可以执行第二个参数的命令
02:第一个参数需要在第三个参数中的中有匹配,不然echo会返回第三个参数而不执行命令。
漏洞形成的原因
cve-2016-5734的漏洞问题出现在TableSearch.class.php中的_getRegexReplaceRows函数,让我们看看这个函数:
replaceWith可以看到在preg_replace中被引用,让我们回溯这两个变量,在getReplacePreview中有调用_getRegexReplaceRows函数
继续回溯,在tbl_find_replace中有调用getReplacePreview,同时参数是post传入,下面让我们看看如何利用构造
phpMyAdmin远程代码执行漏洞构造利用
漏洞利用思路:这个漏洞目前没法直接利用,因为有token限制,需要登陆抓到token,同时需要构造第三个参数保证和第一个参数匹配上,第一个参数可控,但是第三个参数是从数据库中取出的,所以只能提前插入到数据库中,然后再取出来,columnIndex是取出字段值的可控,所以第三个参数也可控了。
流程大概走了一圈,下面看看怎么构造,首先这个漏洞需要有创建表插入字段权限的账号,这里直接用的root账号测试的,先创建个表,然后表中插入个字段值为"0/e"
所以利用构造大概就是这样
组合后是这样//preg_replace('/0/e','phpinfo()','0/e');,这样漏洞就构造好了。
总结:这个pre_replace引发的漏洞在PHP版本4.3.0-5.4.6中能触发,PHP 5.4.7后就不行了。phpmyadmin在4.6.3中修复了这个漏洞,所以要尽快升级。漏洞影响范围:PhpMyAdmin 4.3.0 - 4.6.2
环境搭建
源码下载地址:
https://github.com/vulhub/vulhub/tree/master/phpmyadmin/CVE-2016-5734
运行如下命令启动PHP 5.3 + Apache + phpMyAdmin 4.4.15.6:
docker-compose up -d
启动后,访问http://your-ip:8080,即可看到phpMyAdmin的登录页面。使用root:root登录。
漏洞复现
这个功能需要登录,且能够写入数据。
因为目标环境使用root,所以我们可以创建一个临时数据库和数据表,进行漏洞利用。这里,我们使用cve-2016-5734.pyPOC来复现漏洞。
python cve-2016-5734.py -c 'system(id);' -u root -p root -d test http://your-ip:5734/
-d是已经可以写的数据库,-c是待执行的PHP语句,如果没有指定表名,这个POC会创建一个名为prgpwn的表。