[HCTF 2018]WarmUp1
http://ca039961-2ebb-4acd-8107-ece077539106.node4.buuoj.cn:81/
按F12查看源码
根据提示访问source.php
分析源码,搞懂其中几个函数
mb_strpos() :返回要查找的字符串在要检查的字符串中首次出现的位置
mb_strpos (haystack ,needle)
//haystack:要被检查的字符串。
//needle:要搜索的字符串。
mb_substr() : 是返回字符串的一部分
mb_substr(str ,start ,length, encoding)
//str: 必需,从该 string 中提取子字符串。
//start: 必需,1. 规定在字符串的何处开始2. 正数 - 在字符串的指定位置开始 负数 - 在从字符串结尾的指定位置开始 3. 0 - 在字符串中的第一个字符处开始
//length: 可选,规定要返回的字符串长度。1. 默认是直到字符串的结尾。2. 正数 - 从 start 参数所在的位置返回3. 负数 - 从字符串末端返回
//encoding: 可选。字符编码。如果省略,则使用内部字符编码。
然后根据源码访问hint.php
拿到flag所在的文件名
然后分析源码逻辑,先不看这个emmm类,根据这个if语句可以知道必须满足三个条件,才会执行include操作(文件包含漏洞),否则输出开头那个滑稽脸
if (! empty($_REQUEST['file'])//文件名不为空
&& is_string($_REQUEST['file'])//文件名是字符串
&& emmm::checkFile($_REQUEST['file'])//emmm::checkFile()函数返回true
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
然后分析emmm类中的checkFile函数,一共进行了三次白名单检测、两次问号过滤、一次URL解码。
class emmm
{
public static function checkFile(&$page)
{
//白名单列表
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
//isset()判断变量是否声明 is_string()判断变量是否是字符串 &&用了逻辑与两个值都为真才执行if里面的值
if (! isset($page) || !is_string($page)) {
echo "you can't see it A";
return false;
}
//检测传进来的值是否匹配白名单列表$whitelist 如果有则执行真
if (in_array($page, $whitelist)) {
return true;
}
//过滤问号的函数(如果$page的值有?则从?之前提取字符串)
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')//返回$page.?里?号出现的第一个位置
);
//第二次检测传进来的值是否匹配白名单列表$whitelist 如果有则执行真
if (in_array($_page, $whitelist)) {
return true;
}
//url对$page解码
$_page = urldecode($page);
//第二次过滤问号的函数(如果$page的值有?则从?之前提取字符串)
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
//第三次检测传进来的值是否匹配白名单列表$whitelist 如果有则执行真
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}
在page内容中加入 ?,就能实现截断的效果,这个时候page将会验证 ? 前方的 str 是否包含在whitelist中,因此就能实现checkFile函数的绕过,在第二次检测传进来的值是否匹配白名单列表的时候就返回真,然后执行include,构造语句如下:
tips:
mb_strpos()函数总结:
1、mb_strpos()函数是基于字符数进行查出返回的,第一个字符的位置是0,第二个字符的位置是1,以次类推。
2、mb_strpos()函数返回查找到字符串的首次出现的位置,如果不存在则返回 false
3、使用mb_strpos()函数对中文字符进行操作时,尽量要对页面的编码类型进行声明一下
substr() 函数只针对英文字符,如果要分割的中文文字则需要使用 mb_substr()