[HCTF 2018]WarmUp——PHP代码审计
- 打开题目链接,右键点击查看源码,发现
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)) { //is_string() 函数用于检测变量是否是字符串
echo "you can't see it";
return false;
}
if (in_array($page, $whitelist)) { //in_array() 函数搜索数组中是否存在指定的值
return true;
}
$_page = mb_substr( //mb_substr() 函数返回字符串的一部分
$page,
0,
mb_strpos($page . '?', '?') //mb_strpos — 查找字符串在另一个字符串中首次出现的位置
);
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\" />";
}
?>
- 发现
hint.php
文件,访问发现提示flag
不在这儿 - 观察到如果满足相应的条件,最后是
include
引入文件,所以这个信息很有用。我们只需使emmm::checkFile($_REQUEST['file']
返回值为true
,利用../
跳转目录读取flag即可。观察checkFile
函数,几个if
语句并列,只要我们满足其中一个true
,即有返回值。
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
//mb_strpos //查找字符串在另一个字符串中首次出现的位置
);
if (in_array($_page, $whitelist)) {
return true;
}
第一个截取的代码就是关键点,代码要求输入的必须拥有白名单中的内容,我们直接可以在第一次截取时匹配到白名单的内容,接下来一匹配即可返回true
。现在假设payload
为:file=source.php?/../ffffllllaaaagggg
,经过mb_strpos
为source.php?/../ffffllllaaaagggg?
,但是mb_strpos
这个函数只返回首次出现的位置,所以还是会返回第一个?
的位置,而mb_substr
截取函数,从0
开始截取一直到第一个?
的位置,截取内容为source.php
,恰好能与白名单中的进行匹配,可以return true
;所以通过第一次截取进行绕过。接下来利用/
使source.php?
成为一个不存在的目录,最后include
利用../
跳转目录读取flag
即可
payload为
?file=source.php?/../../../../../ffffllllaaaagggg
[极客大挑战 2019]Havefun——简单的get传参
F12
打开开发者工具栏,可以看到有关get
请求的一段代码,get
传参传入cat=dog
即可得到flag。