今天看了一下BUUCTF第一道题,就考了一道以前的CVE,现在越来越发现,赛事难度如果想要上去通常都是直接上出现过的漏洞,所以想了想还是准备做做CVE的代码审计吧.
这个洞是phpMyAdmin上面的任意文件包含漏洞,<!--more-->出现问题源码如下:
通过源码可以知道,需要让传入参数'target'被包含,需要满足以下条件:
- target值不为空
- taget值需要为字符
- taget参数字符开头不能出现index
- target传入参数不能是$target_blacklist里的值
- 需要经过Core类里的checkPageValidity方法校验
前面三个不需要多说,$target_blacklist里面的值只有'import.php','export.php'

也就是前面四步我们都是可以控制绕过的,然后就来看看checkPageValidity是怎样校验的,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是否存在且为字符串($page<=>$_REQUSET['target'])
-->判断$page的值是否在白名单内,然后为$page连接一个'?',并只截取开头至'?'的字符串
-->再次判断新的$page值是否在白名单里,在就结束该方法并返回真
-->进行一次url解码,再次连接'?',并截取$page开头至'?'部分的字符串
-->最后再判断一次是否$page在白名单内,在就结束返回真
大概就是这样的流程,接着来看payloadhttps://(你的Ip)/index.php?target=db_search.php%253f../../../../../../../../etc/passwd
敏感文件就已经被暴露出来了,接着我们再来分析一下这个过程经历了什么通过传入的payload可知,$_REQUEST['target']="db_search.php%253f../../../../../../../../etc/passwd"
直接经过传入时前三步的校验,来到了第四步
-->传入参数(下面用$page)指代
-->调用定义好的白名单
-->判断$page不为空,且是字符串,接着运行
-->判断当前$page值不在白名单内,接着运行,开始分割传入参数
-->分割后$page仍为'db_search.php%253f../../../../../../../../etc/passwd'
-->判断该值是否在白名单内,仍然不在,再进行下面一步
-->进行一次url解码,由于浏览器已经帮我们解了一次码,并且在这条语句中还被连接了一个'?',现在$page值为"db_search.php?../../../../../../../../etc/passwd?"
-->再次进行分割得到,$page值为"db_search.php"
-->在白名单内,返回真,该方法结束
(由于该方法只是判断,并没有改变传入的'target'的值)
-->此时target值仍为"db_search.php%253f../../../../../../../../etc/passwd"
-->调用include,由于传入payload构造原因db_search.php%253f被解析成为目录,然后一直往父级跳,最后将/etc/passwd包含进来,从而读取敏感文件.
最后是利用方法了,
SELECT '<?=phpinfo()?>';
然后查看自己的sessionid(cookie中phpMyAdmin的值),然后包含session文件即可
第二种方法



--------------the end-------------------