php代码审计之preg_replace引发的phpmyadmin(4.3.0-4.6.2)命令执行漏洞

天融信阿尔法实验室 李喆

这里拿cve-2016-5734讲讲preg_replace引发的命令执行漏洞,漏洞在exploit-db上有利用脚本,经过测试没有问题。这里对这个漏洞进行一下回溯跟踪来解释下preg_replace这个正则替换函数带来的问题。

0×01 漏洞触发原理

preg_replace漏洞触发有两个前提:

01:第一个参数需要e标识符,有了它可以执行第二个参数的命令

02:第一个参数需要在第三个参数中的中有匹配,不然echo会返回第三个参数而不执行命令,举个例子:

//echo preg_replace(‘/test/e’, ‘phpinfo()’, ‘just test’);这样是可以执行命令的

//echo preg_replace(‘/test/e’, ‘phpinfo()’, ‘just tesxt’); 或者echo preg_replace(‘/tesxt/e’, ‘phpinfo()’, ‘just test’); 这两种没有匹配上,所以返回值是第三个参数,不会执行命令

0×02 触发漏洞位置回溯

cve-2016-5734的漏洞问题出现在TableSearch.class.php中的_getRegexReplaceRows函数,让我们看看这个函数:

1-my

 

$find ,和 $replaceWith可以看到在preg_replace中被引用,让我们回溯这两个变量,在getReplacePreview中有调用_getRegexReplaceRows函数

2-my

 

继续回溯,在tbl_find_replace中有调用getReplacePreview,同时参数是post传入,下面让我们看看如何利用构造

3-muy

 

0×03构造利用

漏洞利用思路:这个漏洞目前没法直接利用,因为有token限制,需要登陆抓到token,同时需要构造第三个参数保证和第一个参数匹配上,第一个参数可控,但是第三个参数是从数据库中取出的,所以只能提前插入到数据库中,然后再取出来,columnIndex是取出字段值的可控,所以第三个参数也可控了。

 

流程大概走了一圈,下面看看怎么构造,首先这个漏洞需要有创建表插入字段权限的账号,这里直接用的root账号测试的,先创建个表,然后表中插入个字段值为“0/e”4-my

 

所以利用构造大概就是这样

//$find = ’0/e’;

//$fromsqldata = ’0/e’;
//echo preg_replace(“/”.$find.”\0/”,$_POST["replaceWith"],$fromsqldata);

 

组合后是这样//preg_replace(‘/0/e’,'phpinfo()’,’0/e‘);,这样漏洞就构造好了。

总结:这个pre_replace引发的漏洞在4.3.0和5.4.6中能触发,4.7后就不行了。phpmyadmin在4.6.3中修复了这个漏洞,所以要尽快升级。

 

Written by lizhe