您的位置:首页 > 其它

[HCTF 2018]WarmUp

2020-06-02 05:57 399 查看

之前比赛时候就有碰见这个,但不知为什么把这个题给忘记了,直到buu做题的时候发现了,这次把思路记下来,防止我又忘记hhhhhh

打开后查看源码,看到注释

在链接后面添加/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的内容,提示flag在ffffflllllaaaaaggggg

if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])

在最下面进行判断,file传参不为空,并且为字符型还要通过checkfile要求

回到最上面看checkfile函数
一共四个if
分别进行分析

$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}

$page
不存在或者不是字符串的时候输出“you can’t see it”,并且返回false
所以这个if绕过必须是存在
$page
并且为字符型

if (in_array($page, $whitelist)) {
return true;
}

第二个if就是

$page
必须在白名单里面,也就是必须为source.php或者hint.php

$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}

首先分析一下

$_page
是什么
mb_strpos:返回字符第一次出现的位置
mb_substr:返回从0开始 到mb_strpos函数出现中间的内容
所以
$_page
就是?之前的内容
在经过if语句判断,必须要是白名单里面的内容

$_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;
}
}

$_page
进行url解码后继续截取?前的内容,然后判断是否为白名单里的内容

这里URL解码了一次

$page
值,

这里需要注意的是,PHP中

$_GET、$_POST、$_REQUEST
这类函数在提取参数值时会URL解码一次

而这里在代码中又一次URL解码了一次,共计解码了两次,所以我们也需要对传入的值进行两次URL编码
我们的突破点就在于这段代码只会截取?之前的字符串拿去和whitelist比对,因此只要确保?前的值是source.php或hint.php即可返回true
等同于 /source.php?file=source.php%253f123456 便可以使用include()函数包含 source.php?123456 这个文件(%253f是?URL编码两次后的值)

所以构造payload为:
因为不知道具体flag位置,所以使用文件包含进行利用
?file=hint.php%3f…/…/…/…/…/ffffllllaaaagggg
直到flag出现

总结:这个题目不仅考察代码审计,而且利用了文件包含漏洞

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: