BYPASS WAF实际是去寻找位于WAF设备之后处理应用层数据包的硬件或软件的特性。利用特性构造WAF不能命中,但是在应用程序能够成功执行的载荷,绕过防护。
寻找真实IP
云WAF通过修改DNS解析隐藏了真实IP地址;
查找域名解析记录;
利用邮件发送功能来抓包,获取真实IP。
畸形数据包bypass
GET型请求转POST型;
Content-length头长度大于4008;
正常参数放在垃圾数据后边。
某些Apache版本(version 2.*)在做GET请求的时候,无论method为何值均会取出GET的内容,如请求为method为DOTA2,依然返回了aid为2的结果。
如果某些WAF在处理数据的时候严格按照GET,POST等方式来获取数据,就会因为Apache的宽松的请求方式导致bypass。
实例:
环境:DVWA+PHPstudy,burpsuite
目的:测试某些Apache版本与WAF解析request时的不同。
进入靶场后更换等级为LOW,来到Command INjection页面。
打开burpsuite开启浏览器代理截获请求。
这里我们点击右下角View source按钮发送一个GET请求。
我们可以看到burpsuite拦截率request,在这个页面我们将第一行的GET随意改成其他,点击forword通过该请求。
之后我们点击bp的target页面找到我们刚刚发送的ZSYYY请求。
我们可以发现request中的头部信息并不是GET请求,而是我们刚刚输入的ZSYYY。然而repose则给我们返回了正常的页面,并且我们成功跳转出了源码页面,证明我们的畸形method被解析成了GET依旧可以正常得到reponse。
这种方式就是通过Apache与waf解析请求头部的差异达到bypass的目的。
php在解析multipart data的时候有自己的特性,对于boundary的识别,只取逗号前边的内容,例如我们设置的boundary为------aaaa,1234,php在解析的时候只识别了------aaaa,后边的内容均没有被识别。然而WAF在做解析的时候,可能获取的是整个字符串,此时就可以BYPASS。
什么是multipart data?
Multipart/from-data的请求方式来完成上传图片等服务器交互操作,这需要我们去严格按照规范的格式去组装请求体,每个换行和空格都是不可忽略的。
实例:
DVWA切换到file upload。
上传1.png,抓包查看数据包。
可以看到存在四个分割符,点击forward,正常上传成功。我们接着上传2.png,将分隔符后边的内容进行修改,查看是否可以上传成功。
将原始的分隔符后边添加,1,在第一个和最后一个后边同样添加,1,点击forward,发现也可以上传成功,也就是说,php在解析分隔符时会自动忽略,之后的内容正常解析请求,某些WAF可能会把这些content-disposition识别为一整串内容,从而达到bypass的效果。
在asp+IIS的环境中存在一个特性,特殊符号%,在该环境下当我们输入s%elect的时候,waf层可能解析出来的结果是s%elect,但是在iis+asp的环境下解析的结果为select。
实例:
环境:asp+iis
<form method="get" action="simpleform.asp">
<p>First Name:<input type="text" name="fname"/>p>
<p>Last Name:<input type="text" name="lname"/>p>
<input type="submit" value="Submit"/>
form>
<boby>
Welcome
<%
response.write(request.querystring("fname"))
response.write("" & request.querystring("lname"))
%>
boby>
IIS服务器支持对unicode的解析,例如我们对于select中的字符进行unicode编码,可以得到s%u0065%u006cect,在登录框输入查看结果。
我们可以看到用unicode编码将el进行替换,但iis服务器在此处处理时会将%转化为%25,只需在URL地址栏将多余的25删掉,回车后可以看到IIS自动将unicode解析为select,一些WAF会接受原本的%u0065%u006,从而产生差异达到BYPASS的效果。
该漏洞主要利用unicode中的e对应的unicode为%u0065,但是%u00f0同样会被转换为e。
(1)s%u0065lect=>select
(2)s%u00f0lect=>select
WAF层可能会识别(1)的形式不会识别(2)的形式,可以利用做WAF的绕过。
可以看到,无论是(1)还是(2)都被处理为e。
双重url编码,即对于浏览器发送的数据进行了两次urlencode操作,比如s做一次的url编码为%73,再对%73做一次编码为%25%37%33.一般情况下数据经过WAF设备的时候只会做一次url编码,这样解码之后的数据一般不会匹配到规则,达到bypass的效果。
%73elect
%25%37%33elect
虽然我们的实验并不存在waf,本质的原理一样,就是通过WAF可能没有进行多重解码的漏洞达到bypass的效果,如果存在waf,输入%25%37%33elect可能会被解析为%73elect,iis服务器接着将%73elect解析为select。
实例:
打开dvwa靶场,将安全级别调整为low,进去sql injection一栏。
随后我们在该页面尝试进行sql注入,注入语句如下:
?id=-1' union select 1,version()#
如果存在WAF对GET请求方式进行了过滤,我们可以尝试使用POST方式进行sql注入。
右击选择change request method即可切换提交方式。
实例:
前提WAF对get和常规的post请求方式进行了过滤,则我们尝试使用from-data格式进行注入。
在重发器右击选择change boby encoding。
因此,我们可以通过转换GET和POST请求,并且改变POST请求格式来达到bypass的效果。
HPP是指HTTP参数污染。
?id=1&id=2&id=3的形式,这种形式在获取ID值的时候不同的web版本获取的值不一样。
假设提交的参数为:
id=1&id=2&id=3
Asp.net+IIS 获取的值为id=1,2,3
Asp+IIS获取的值为id=1,2,3
Php+Apache获取的值为id=3
可以分析:当waf获取参数的形式与web程序参数不一样时,就可能会出现bypass waf的可能。
关键还是要分析WAF对于参数的获取方式是如何处理的。对于HPP的灵活运用,一些CMS基于url白名单,可以利用hpp,在参数一的位置添加白名单目录,在参数二的位置添加恶意的payload,形如Index.php?a=[whilelist]&a=se;ect 1 union select 2
数据库层bypass通常是在bypass waf的sql注入防护规则。我们需要针对数据库使用该数据库的特征即可。如mysql,sqlserver等。
mid(version(),1,1)
substr(version(),1,1)
substring(version(),1,1)
lpad(version(),1,1)
rpad(version(),1,1)
left(version(),1,1)
reverse(right(reverse(version()),1)
concat(version(),'|',user())
concat_ws('|',1,2,3)1
ascii(1)
hex('a')
unhex(66)
limit 1 offset 1
mid(version() from 1 for 10)
通过join拼接
(1)空白符号
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需要做urlencode,mssql中表示空白字符比较多,靠黑名单去阻断不太合适。
(2)注释符/**/
(3)其他符合:.符号
例如:
select * from. table1;
(1)空白字符
(2)注释符号
例如:
select /**/ * from table1;
(1)空白字符
(2)注释符号
(3):号在sqlserver2017版本以前可以
实例:
构造一个查询语句:
select * from t1 where quantity>152; exec(‘wa’+‘itfor delay’‘0:0:5’‘’)
可以延时5秒,分割字符串达到绕过WAF的效果。