[HCTF 2018]WarmUp 1
前言
个人观点,若有误请指教
解题思路及步骤
-
由于点开后只是一个表情包,所以查看html源码,发现一个提示
-
根据提示访问source.php文件,正式开始代码审计环节
<?php
//打印代码,之所以能在浏览器看到php源码就因为这个
highlight_file(__FILE__);
class emmm
{
//&为引用,即在函数修改会改变外面的,但在这里应该没用,因为是通过这个$_REQUEST['file']传参的,而不是一个变量名。
//另一个证明没用的是如果有用,那还怎么文件包含????
public static function checkFile(&$page)
{
//白名单列表
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
//isset()判断变量是否声明 is_string()判断变量是否是字符串
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
//检测传进来的值是否匹配白名单列表$whitelist(只跟==>后面的比较) 如果有则为真
//通过这个其实也可以判断出来source.php与hint.php是在同一目录下的,因为在include(路径),路径是一致的。
if (in_array($page, $whitelist)) {
return true;
}
//mb_substr截取函数(字符串,开始位置,截取长度)
//mb_strpos()函数返回被查找的字符串在另一字符串中首次出现的位置(下标从0开始)
//如果$page的值有?,则字符串只剩下在?之前的字符,若无则截取整个$page
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
//第二次检测传进来的值是否匹配白名单列表$whitelist 如果有则为真
if (in_array($_page, $whitelist)) {
return true;
}
//对$page中的url编码字符进行解码,如%23变成#
$_page = urldecode($page);
//再进行一次上面的操作
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
//第三次检测传进来的值是否匹配白名单列表$whitelist 如果有则为真
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}
//empty函数判断file值是否为空,is_string判断file值是否为字符串(通过$_REQUEST获得的会默认加引号的),调用checkFile函数来进行最后判断。
//即其关键在于传了文件包含漏洞的payload之后,还使checkFile返回真。
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\" />";
}
?>
通过代码审计,我们可以发现checkFile返回真的地方一共有三处,但对于上传payload可以利用的地方只有最后两处。(第一处用不了,因为file就等于hint.php,这样叫payload?)
-
访问hint.php,获得提示
-
payload环节
①对于第二个返回真的地方,我们可以注入file=hint.php?/…/…/…/…/…/…/…/…/ffffllllaaaagggg
注:在第二处判断之前先进行截取了?之前的字符串,即在此之后的$page等于hint.php。
②对于第三个返回真的地方,我们可以注入file=hint.php%253f/…/…/…/…/…/…/…/…/ffffllllaaaagggg
注:一般情况下,在地址栏中一些字符需要用url编码进行输入(如想在地址栏中输入#则需要输入%23),而在后台服务器中会自动进行解码,获得原始的字符。而在这道题中的代码会自己再进行一次解码。但payload想返回真就需要有问号,那么我们可以对问号进行两次编码。
总结
-
在解这道题时只能做到出现flag not here, and flag in ffffllllaaaagggg字眼,对于文件上传漏洞极其不熟,而且在代码审计时对函数的返回真的情况出现了误解。o(╥﹏╥)o
-
为什么hint.php?/…/…/…/…/…/…/…/…/ffffllllaaaagggg就可以访问到ffffllllaaaagggg文件?
include 函数把hint.php? 当成一个文件夹(不论你是否真实存在,include函数都认为它有) ,然后在进行一层一层地返回上级。
该题的include函数会先进到hint.php文件夹(实际上不存在)中再一层层的返回。
注:来自https://blog.csdn.net/FY10033/article/details/119950878