查看源代码:
发现提示:source.php
访问source.php
代码审计题目:
源代码:
<?php
// 高亮显示当前文件的内容
highlight_file(__FILE__);
// 定义一个名为emmm的类
class emmm
{
// 定义一个静态方法checkFile,用于检查传入的文件名是否合法
public static function checkFile(&$page)
{
// 定义白名单,只允许访问source.php和hint.php两个文件
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
// 检查$page变量是否已设置且为字符串类型
if (! isset($page) || !is_string($page)) {
echo "you can't see it"; // 如果不是,输出提示信息并返回false
return false;
}
// 检查$page是否在白名单中
if (in_array($page, $whitelist)) {
return true; // 如果是,直接返回true
}
// 尝试去除$page中的查询字符串(?后面的部分),并检查剩余部分是否在白名单中
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?') // 确保即使在$page中没有'?'时也能正常工作
);
if (in_array($_page, $whitelist)) {
return true; // 如果剩余部分在白名单中,返回true
}
// 对$page进行URL解码,然后再次尝试去除查询字符串并检查
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?') // 同上,确保能处理没有'?'的情况
);
if (in_array($_page, $whitelist)) {
return true; // 如果URL解码后的剩余部分在白名单中,返回true
}
// 如果以上条件都不满足,输出提示信息并返回false
echo "you can't see it";
return false;
}
}
// 检查是否通过_REQUEST接收到了'file'参数,并且该参数是字符串类型,以及通过emmm::checkFile()方法验证通过
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\" />";
}
?>
首先要弄懂几个函数的用法:
$_REQUEST
是一个超全局变量,它包含了 $_GET
、$_POST
和 $_COOKIE
empty()
是一个语言构造(而不是一个函数),用于检查一个变量是否为空。
is_string()
用于检测变量是否是字符串类型。如果给定的变量是字符串,则返回 true
;否则,返回 false
。
isset()
是一个语言构造(而非函数),用于检测变量是否已设置并且非 NULL
。如果变量存在并且其值不是 NULL
,则返回 true。
in_array()
用于检查数组中是否存在某个值。如果找到了值,则返回 true
;如果没有找到,则返回 false。
mb_substr()
用于从多字节字符串中截取子串。
mb_substr ( string $str , int $start [, int $length = NULL [, string $encoding = mb_internal_encoding() ]] )
- $str:要截取的字符串。
- $start:截取开始的位置(偏移量)。如果是正数,则从字符串的开头开始计算;如果是负数,则从字符串的末尾开始计算。
- **length∗∗(可选):要截取的长度。如果省略或设置为‘NULL‘,则截取从‘start` 位置到字符串末尾的所有字符。
- $encoding(可选):字符编码。如果省略,则使用内部字符编码(
mb_internal_encoding()
的返回值)。
mb_strpos()
用于查找字符串首次出现的位置。
mb_strpos ( string $haystack , string $needle , int $offset = 0 , string $encoding = mb_internal_encoding() )
- $haystack:被搜索的字符串。
- $needle:要查找的字符串。
- $offset:(可选)从 haystack 中的哪个位置开始搜索。
- $encoding:(可选)字符编码。如果省略,则使用内部字符编码
分析整个题目,需要执行include $_REQUEST['file'];以获得flag。
其中emmm::checkFile($_REQUEST['file']) 应为true;
分析checkFile方法,先传入参数hint.php, 得到flag文件名:
构造参数
../ 是指上一级目录,向上找五级目录得到flag。