phpmyadmin 4.8.1 远程文件包含漏洞(CVE-2018-12613)

phpmyadmin 4.8.1 远程文件包含漏洞(CVE-2018-12613)

$target_blacklist = array (
    'import.php', 'export.php'
);

// If we have a valid target, let's load that script instead
if (! empty($_REQUEST['target'])
    && is_string($_REQUEST['target'])
    && ! preg_match('/^index/', $_REQUEST['target'])
    && ! in_array($_REQUEST['target'], $target_blacklist)
    && Core::checkPageValidity($_REQUEST['target'])
) {
    include $_REQUEST['target'];
    exit;
}

你需要:
1.$_REQUEST['target']不为空
2.$_REQUEST['target']是字符串
3.$_REQUEST['target']不以index开头
4.$_REQUEST['target']不在$target_blacklist中
‘import.php’, ‘export.php’
5.Core::checkPageValidity($_REQUEST['target'])为真
代码在libraries\classes\Core.php 443-476行

check函数本身

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;
    }

上面提到的whitelist就是白名单

$_page是取出$page问号前的东西,是考虑到target有参数的情况,只要$_page在白名单中就直接return true
但还考虑了url编码的情况,所以如果这步判断未成功,下一步又进行url解码

看似能够非常完美地能够验证请求的文件是正确的,但是利用url二次编码就可以绕过了。

由于服务器会自动解码一次,所以在checkPageValidity()中,$page的值一开始会是db_datadict.php%3f,又一次url解码后变成了db_datadict.php?,这次便符合了?前内容在白名单的要求,函数返回true
但在index.php中$_REQUEST[‘target’]仍然是db_datadict.php%3f,而且会被include,通过目录穿越,就可造成任意文件包含

其实也就是说在返回true的前提下进行目录穿越就可以了,直接的?,也是可以的

posted @ 2021-09-13 15:59  Sayo-NERV  阅读(47)  评论(0编辑  收藏  举报