本文最后更新于 559 天前,其中的信息可能已经有所发展或是发生改变。
WarmUp1:https://buuoj.cn/challenges#[HCTF%202018]WarmUp
点入链接按下F12发现提示
打开source.php页面开始代码审计
<?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
// 判断传入的$page是如果不是字符串或者为空的话返回false
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
// 判断$page是否存在于数组里,如果在返回true
if (in_array($page, $whitelist)) {
return true;
}
// 截取$page.?问号第一次出现之前的部分为$_page
$_page = mb_substr(
$page,
0,
mb_strpos($page.'?', '?')
);
// 判断$_page是否存在于数组里,如果在返回true
if (in_array($_page, $whitelist)) {
return true;
}
// 对$page的内容进行urldecode解码
$_page = urldecode($page);
// 截取$_page.?问号第一次出现之前的部分为$_page
$_page = mb_substr(
$_page,
0,
mb_strpos($_page.'?', '?')
);
// 判断$_page是否存在于数组里,如果在返回true
if (in_array($_page, $whitelist)) {
return true;
}
// 如果判断全部没有返回这返回false
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\" />";
}
?>
代码审计完接下来的就是绕过了,首先要满足in_array这个条件,那么传入的参数就必须包含source.php或hint.php
GET http://url/source.php?file=hint.php
查看了这个文件的内容得知了flag在ffffllllaaaagggg这个文件中
第二步就是构造读取这个文件的payload了,首先我们要知道在使用urldecode会出现一个问题,假如我将一个字符使用url编码了两遍然后传入的时候,首先浏览器解码了一遍,接下来才是urlencode解码,如果这个时候你后端代码进行过滤内容在urlencode解码之前的话这个内容是过滤不出来的
这题就出现了这个问题,首先前三个if是过不了的,但是到第四个的时候有些不一样,先进行了url解码在进行截取然后再去比对,我们手动把一个问号url编码两次为%253f,拼接到hint.php后面,前三个if没有进行urlencode解码无法触发,第四个if处将其解码为?, 下一步进行截断对比的时候就能成功通过返回true,参数效验通过,触发文件包含
ffffllllaaaagggg具体的层级就得遍历来试出来了
GET http://url/source.php?file=hint.php%253f../../../../../ffffllllaaaagggg
浏览量: 45