BUUCTF [HCTF 2018]WarmUp
先瞅瞅
进入环境,只有一只大大的滑稽,看一下源代码
源代码如下所示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!--source.php-->
<br><img src="https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg" /></body>
</html>
在里面看到了source.php,访问一下,发现了网页的源码,大概审计一下,分析内容写在注释里
<?php
//高亮显示file
highlight_file(__FILE__);
class emmm
{
//一个函数,参数是我们输入的参数$page,传入的是&$page
public static function checkFile(&$page)
{
//定义了一个白名单,里面是source.php、hint.php
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
//isset()用来检测$page是否定义,is_string判断其是否是字符串,不满足会直接返回false
if (! isset($page) || !is_string($page)) {
echo "you can not see it";
return false;
}
//这里是如果输入内容在白名单里就会返回true
if (in_array($page, $whitelist)) {
return true;
}
/*这里将$page中?之前的内容截取出来
mb_strpos($page . '?', '?')中第一个参数$page . '?'是先在$page之后拼接一个?,可能是为了防止找不到问号而发生奇怪的事 情,然后第二个参数就是说要返回?的位置,mb_substr()函数就是将$page 中?之前的内容剪出来,比如我们的输入是?file=source.php?flag时,$page是source.php?flag,然后$_page就是source.php
*/
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
//这里是判断$_page是否在白名单里,是的话返回true
if (in_array($_page, $whitelist)) {
return true;
}
//这里对$page进行url解码并将结果赋给$_page
$_page = urldecode($page);
//这里也是提取?之前的内容
$_page = mb_substr(
$_page,0,mb_strpos($_page . '?', '?')
);
//这里也是判断白名单
if (in_array($_page, $whitelist)) {
return true;
}
//如果之前都没有匹配上,就会返回false
echo "you can not 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,发现了flag的位置
由于checkFile函数传入的参数是以引用方式传入的,所以在对$page剪切时会对file直接操作,我们用于绕过的内容会被剪掉,所以include可以正确的去找我们要的文件。
然后开始尝试构造payload,判断函数一共有三个地方可以返回true,第一个没有进行任何操作,只能输入为source.php或者hint.php,显然拿不到flag。
对于第二个返回true的地方,我们可以构造payload为file=source.php?ffffllllaaaagggg
或者file=hint.php?ffffllllaaaagggg
尝试一下http://77d66993-5e70-49b1-9bbd-93b8cdb3d113.node3.buuoj.cn/source.php?file=source.php?ffffllllaaaagggg
,发现没有任何东西,可见我们的方法对了,但是文件不在当前目录,可以一次次加../
,加到第五次的时候返回了flag,最终payload为http://77d66993-5e70-49b1-9bbd-93b8cdb3d113.node3.buuoj.cn/source.php?file=source.php?../../../../../ffffllllaaaagggg
,其中file=
后面也可以替换成hint.php
对于第三个返回true的地方,只需要将?两次url编码就好了,之所以两次是因为这个url传给服务器时会先进行一次url解码,又在脚本里被解码一次,要得到?只能编码两次
payload就是http://77d66993-5e70-49b1-9bbd-93b8cdb3d113.node3.buuoj.cn/source.php?file=source.php%253F../../../../../ffffllllaaaagggg
,同样可以得到flag