WarmUp
进来一个滑稽表情包,查看页面源码,得到提示
<-- source.php -->访问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\" />";
}
?> 审计一下php代码,需要使用GET方式提交一个 $file 变量,进行文件包含。
看到白名单,随即访问hint.php,得到ffffllllaaaagggg文件名。
多次if语句判断,第一次判断是否存在 $page 变量且是否为字符串,简单绕过。
第二层 if 用到了bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] ) 函数:
如果满足了就 return true。关于 bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] ) 函数有它的设计缺陷,当进行弱比较的时候会进行弱类型转换,从而绕过对数字的审查。大致可以看这篇参考文章:PHP代码审计Day1 - in_array函数缺陷。
在这里由于数组类型是字符串类型,所以不存在这样的弱类型转换漏洞,这里如果需要返回 true,则必须 $page 的值为 hint.php 或者 source.php。
这部分用到了两个比较新的 php 函数:
与 substr() 函数不同的是,mb_substr() 通常用来分割多种字符,用于兼容字符集。例如:
这看起来似乎更符合中国人的习惯。
该函数用来返回字符串 $needle 在 $haystack 字符串中第一次出现的位置。这里就存在绕过,只要题目中的字符串中出现问号,就可以对字符串进行截断,从而绕过白名单的审查。
于是只要构造这样的字符串:
就可以绕过白名单审计,返回 true。
接下来就是简单的目录穿越完事,可以先读取 /etc/passwd:
穿越回根目录经过五次,大概推测文件结构,然后读取flag。
Last updated