[BSidesCF 2020]Had a bad day
[BSidesCF 2020]Had a bad day
这题还是比较简单的,打开环境里面就两个按钮
输入其他参数都会提示:Sorry, we currently only support woofers and meowers.
第一次猜测是SQL注入,但输入引号测试没效果
然后猜测也可能是布尔注入,于是测试and,结果发现报错了
居然是include。。。
那很明显这不是一道SQL注入的题,传参可以提交要包含的文件名,但他服务器里有什么文件目前还不知道。先尝试用伪协议读源码,但是报错了。
报错信息可以看出,尾缀的php多了一个,应该是被拼接了,删除后缀名再提交就可以了。
拿到源码:
<?php
$file = $_GET['category'];
if(isset($file))
{
if( strpos( $file, "woofers" ) !== false || strpos( $file, "meowers" ) !== false || strpos( $file, "index")){
include ($file . '.php');
}
else{
echo "Sorry, we currently only support woofers and meowers.";
}
}
?>
源码很简单,里面用到了strpos函数,这个就是返回一个字第一次出现的位置,需要注意
如果第一个字在首位出现,则返回0,PHP中弱类型0就是假,所以会导致if判断过不了
解决这题的关键在于PHP目录定位的特点
正常情况下,我们定位文件只需要输入文件地址就可以,但如果输入的文件地址超过了最小的文件夹,无疑会出错
但如果我们用两个点号又返回了上级目录,再访问文件,就又变得可行。
继续研究,如果访问的文件不存在的话,还能不能向上返回目录了?
测试发现,不可以!
但这仅是在Windows的环境下进行的测试,其他的环境还需要具体测试。
Linux环境下的测试:
测试结果可以发现,当最后切换的对象是一个文件而不是一个目录时,Linux的表现和Windows不同,Windows系统可以正常返回当前目录下,而Linux系统会报错。
不同的环境对目录的处理机制不太一样,PHP也不例外。
PHP环境下测试:
测试代码(例题的简化版):
<?php
$file = $_GET['d'];
$b = $file . '.php';
echo $b;
echo "<br>";
if(isset($file))
{
include ($b);
}
?>
测试结果:
多轮测试发现,PHP对文件是否存在不关心,因为他只关心你最终所在的目录位置,甚至中间多套几层也不影响。
但是,如果你最终的目录位置不存在的话,人家该报错还是会报错的,比如下面就少了一层
回归题目,这题就是利用PHP的这个特性完成绕过的。
这题最后就不多啰嗦了,flag文件可以包含进来,没有报错,说明存在该文件,只需要再利用伪协议读源码就行了
payload:?category=php://filter/convert.base64-encode/resource=woofers/sui/bian/da/../../../../flag
base64解码就是flag了!