web
第二题
[HCTF 2018]WarmUp
打开靶场
一张图片
查看网页源代码
发现注释source.php
访问,这是一道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;
}
$_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\" />";
}
?>
尝试访问hint.php
根据提示,flag可能在 ffffllllaaaagggg中
分析源代码
代码的主要部分
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进行3次判断
1.是否为空
2.是否是字符串
3.调用checkFile函数判断file是否满足函数中的条件
如果满足这3个条件,就使用include包含并执行文件
不满足则输出图片
关键就在于checkFile函数
分析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;
}
$_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;
}
首先定义白名单"source"=>“source.php”,“hint”=>“hint.php”
① 第一个if:判断page是否为空或者是否是字符串
② 第二个if:使用in_array函数判断page是否在定义的白名单中
③ 然后使用mb_substr函数截取字符串PHP mb_substr() 函数
注:使用mb_strpos获取page中?所出现的位置php mb_strpos()函数详解
通过mb_substr函数 ,获取到了page中?前面的所有字符,并将其赋给_page
④ 第三个if:判断所截取的字符串是否在白名单中
⑤ 将page进行url解码后的值赋给_page,然后再同③截取_page中?前面的字符串
⑥第四个if:对第⑤步中的字符串进行白名单验证
最后,构造payload
经过上面分析源代码可知,该php代码存在目录穿越和文件包含漏洞
目录穿越与文件包含
初始payload:source.php?file=source.php?../../../../../../ffffllllaaaagggg
上图引用于https://blog.csdn.net/weixin_30129661/article/details/113310997
显然,根据代码分析,它会截取?前面的内容进行判断即source.php,此内容存在于白名单中,就会通过前3个if的判断
由于 存在第四个if判断,需要再次修改payload:将问号进行url编码:
source.php?file=source.php%3F../../../../../../ffffllllaaaagggg
思考:如果只进行一次编码,那么在url栏中输入后,在服务器端会被解析为?,然后经过php代码中的decode解码就会出错
所以需要进行二次编码
即将%3F再次进行编码得到%253F
构造最终payload:source.php?file=source.php%253F../../../../../../ffffllllaaaagggg
此时在url栏中的%253F会被服务器解析为%3F,然后经过php代码的解析,就会变成问号,那么第四个if判断就会满足,因此可以通过checkFile函数的判断