先看网页
按照正常流程,先ip+ls,可以看到flag
但是不能直接得flag,他应该是过滤掉了一点东西。
这里考虑过滤掉了空格
空格过滤绕过:
%20
%09
${IFS}
$IFS$1
{IFS}
<
<>
空格绕过之后发现还是打不开flag.php,但报错语句变了
尝试打开index.php,成功了。
从这里我们可以看出打不开flag.php的原因
代码审计:
preg_match函数:一般形式是preg_match("/xxxx/",$b,$c),其中$c用于储存结果,可以省略
preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)
这里结合下面的die函数,过滤掉了&、/、?、*等字符,由[\x{00}-\x{20}]还过滤掉ascll码为0~32的字符,其中\x为正则表达式中的十六进制转义字符
preg_match("/ /", $ip)
这里就是过滤掉空格的地方了,但是由于刚刚那个函数还过滤掉了一点字符,所以有些空格绕过没法生效
preg_match("/bash/", $ip)
这里过滤掉bash字符串
preg_match("/.*f.*l.*a.*g.*/", $ip)
带有形如.*等字符是正则表达式贪婪匹配的特征,我在下面再详细讲讲
$a = shell_exec("ping -c 4 ".$ip);
shell_exec函数跟system之类的差不多,是执行系统命令的函数,这里是用shell_exec函数执行一个ping命令 ,而-c 4表示了回显请求数量为4
贪婪匹配:
正则表达式中,含有形如.*或.+等字符则代表正则表达式采用贪婪匹配
例子:
设$key='aaacccbbb'
preg_match("a.*b",$key)
则会匹配到aaacccbbb,贪婪匹配就是往字符串越多的方向匹配
这道题中的贪婪匹配的正则表达式为:
preg_match("/.*f.*l.*a.*g.*/", $ip)
这就表明他会按flag的依次顺序匹配字符串,即使是ffflaggg也会被匹配,但flag这四个字符是依次的,如果是形如gfla就没法匹配。当然正常情况下正则表达式是区分大小写的,也就是小写只能匹配小写,大写只能匹配大写,加上/i才不区分大小写。
回到解题,我们之所以空格过滤后没有办法打开flag.php的原因是我们的payload是/?id=127.0.0.1;cat$IFS$1flag.php,很显然第三次正则表达式过滤掉了flag这个字符串,那我们就没有办法直接输入flag了,但文件名摆在那里,一定要用flag,要绕过这个过滤,有以下方法。
方法一:
由于下面的代码时是
$a = shell_exec("ping -c 4 ".$ip)
这里注意,他用的是“ ”而不是‘ ’。双引号会对字符串中的变量进行解析,单引号则不会,而前面的正则表达式过滤flag也只是从字符串上检查是否有flag的字样而已,并没有解析变量,而下面解析了。
payload:
然后就可以在这里找到flag了
方法二:
这个方法需要getshell以及将字符串转化为base64编码。
先提一个知识点
在执行系统命令中,|号有个作用
它可以将前一个命令的输出作为下一个命令输入的参数
例如:echo cat flag|sh就会执行cat flag
payload:
注意这里的base64 -d会输出解码后的base64编码
flag还在这里找
方法三(内联执行):
payload:
?ip=127.0.0.1;cat$IFS$1`ls`
这里的作用是cat用ls命令出来的文件。或者说将``里的输出作为参数传给cat
flag还在那里