目录php
HTTP报文包体的解析html
Transfer-Encodingnginx
Charsetgit
溢量数据程序员
HTTP协议兼容性github
HTTP请求行种的空格web
高层数据tomcat
本文主要从绕过WAF过程当中须要注意的角色和点出发,尝试理解它们的运做,构建一个简单的知识框架。
首先,WAF分为非嵌入型WAF和嵌入型WAF,非嵌入型WAF指的是硬WAF、云WAF、虚拟机WAF之类的;而嵌入型WAF指的是Web容器模块类型的WAF、代码层WAF。非嵌入型WAF对Web流量的解析彻底是靠自身的,而嵌入型WAF拿到的Web数据是已经被解析加工好的。因此非嵌入型的受攻击机面还涉及到其余层面,而嵌入型WAF从Web容器模块类型WAF、代码层WAF往下走,其对抗畸形报文、扫操做绕过的能力愈来愈强。固然,在部署维护成本方面,也是越高的。
有些WAF设置的是针对域名的防御,有些时候,咱们尝试将域名改为ip地址能够绕过WAF的防御。
咱们先来探讨一个问题。HTTP请求的服务器在接收到该请求时,会关心哪些头部字段,以及如何根据这些头部字段作出对Request-body 进行相应的解析处理。说实话,要搞清这些东西,最好仍是查看web容器的源码,但笔者如今还没作到这一步,在这里仅能根据自身的认知说起一些头部字段。这些头部字段的关系,笔者认为能够总结为以下:
Transfer-Encoding(Content-Encoding(Content-Type(charset(data))))
关于Transfer-Encoding,传送门——>数据的分段编码(transfer-encoding)
Apache+php对chunked类型的HTTP请求的处理太怪了。RFC2616中说明了,客户端或服务器,收到的HTTP报文中,若是同时存在chunked与Content-Length,则必定要忽略掉content-length,而在Apache中却不能缺乏。理由是Apache自己是不支持解析chunked的(对于Apache来讲,因为没有解析HTTP请求chunked的代码逻辑,因此必定要从content-length中查看该报文的长度,而chunked多是被PHP解析了的,因此这两个头部必定要同时存在)。这一结论也很好地解释了一些不解的现象,如利用chuncked编码能够绕过安全狗Apache。 经过shodan搜索相关服务器,简单测试一下,关于常见中间件、语言与chuncked的关系有以下参考:
ASPX | PHP | Java | |
Apache | X | Y | |
Nginx | Y | Y | |
IIS | Y | Y | |
Tomcat | X |
那关于chunked,能够有什么利用思路呢? 思路一,构造一个chunked请求体,尝试绕过WAF。其中能够涉及到利用chunked自己的一些规范、特性。 好比,假如WAF会解析chunked,但加入一些chunked的扩展,WAF就解析不了。 反过来,脑洞一下,假如WAF意识到了解析chunked时应该忽略这些扩展,那么在Tomcat下咱们是否是能够利用它一下。
相关文章:利用分块传输吊打全部WAF
Content-Type
Web容器应该不怎么关心Content-Type这个字段,后台语言会识别该字段并进行对应的数据解析。而咱们利用该字段的话,主要从如下思路出发:后台语言会识别哪些类型的Content-Type,这些Content-Type对咱们绕WAF有没有用。 PHP默认会处理application/x-www-form-urlencoded、multipart/form-data两种。而JAVA后台对于multipart/form-data类型Content-Type的识别处理,须要借助三方库或是框架,默认状况下是没法处理的,但如今通常都用框架,而框架可能默认状况下就会识别并处理这类型的请求。 后台接收到application/x-www-form-urlencoded请求的数据时,会本身解码一次,若是开发人员本身又解码一次或屡次,就造成了双重编码、多重编码。 对于multipart/form-data,非嵌入型的WAF与模块类型的WAF,都只能本身识别并解析区分字段内容,因此在这一块你能够发挥本身想象,进行各类骚操做来进行绕过,可是,你应该要确认你当前所要绕过的WAF是否是真的作了这块的内容识别。笔者的意思是说,若是它遇到这种类型Request,只是对Body内容进行所有的规则匹配,而不会解析出其中的表单内容,那你可能就不必进行那些骚操做了。实际上,有的非嵌入型WAF就是这么“懒”。multipart/form-data的相关骚操做能够参考Protocol-Level Evasion of Web Application Firewalls
charset是被添加在Content-Type字段后面的,用来指明消息内容所用的字符集,它也仅被后台语言所关心。
• application/x-www-form-urlencoded;charset=ibm037
• multipart/form-data; charset=ibm037,boundary=blah
• multipart/form-data; boundary=blah ; charset=ibm037
JAVA的Servlet默认是接受大多数的charset的,不过正常点的程序员都会设置强制编码。 有以下示例: 后台代码
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String userName = req.getParameter("user"); resp.getOutputStream().println("username :"+userName); }
请求(Burpsui设置User Options-Character sets-Use a specific ..)
POST /test HTTP/1.1 Host: 127.0.0.1:8081 Content-Type: application/x-www-form-urlencoded; charset=ibm037 Content-Length: 25 %A4%A2%85%99=%99%96%96%A3
输出
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Content-Length: 16 username :root
至少能够支持IBM037, IBM500, cp875, and IBM1026字符集的中间件+语言的状况,能够参考下面表格:
Target | QueryString | POST Body | & and = | URL-encoding |
Nginx, uWSGI – Django – Python3 | ✔ | ✔ | ✔ | ❌ |
Nginx, uWSGI – Django – Python2 | ✔ | ✔ | ❌ | ✔ (sometimes required) |
Apache Tomcat – JSP | ❌ | ✔ | ❌ | ✔ (sometimes required) |
IIS – ASPX (v4.x) | ✔ | ✔ | ❌ | ✔ (optional) |
IIS – ASP classic | ❌ | ❌ | ||
Apache/IIS – PHP | ❌ | ❌ |
笔者当初有时在瞎想,其中想到,会不会存在URI数量过多,产生绕过呢?没想到就存在这样的一个CVE,CVE-2018-9230-OpenResty URI参数溢出漏洞。
不要紧,思想还在嘛,还存在不少的变形,如经过multipart/form-data的方式来发送数据量比较大的报文,但又属于正常的HTTP请求,按照道理来讲,对较上层的WAF(非嵌入型、模块类型)应该会有必定杀伤力的。
传送门——> 绕过网站WAF(图片绕过)
在RFC2616文档中,有说到,HTTP头部字段的构造。
SP = <US-ASCII SP, space (32)> HT = <US-ASCII HT, horizontal-tab (9)> LWS = [CRLF] 1*( SP | HT ) message-header = field-name ":" [ field-value ] field-name = token field-value = *( field-content | LWS ) field-content = <the OCTETs making up the field-value and consisting of either *TEXT or combinations of token, separators, and quoted-string>
简单点来讲就是
Test-Header: Test
等效于(空格替换成\x09)
Test-Header: Test
但笔者发现,在请求行中,你也能够这样作(即使RFC2616 5.1节中指明了请求行中只能用空格)。因而,将一个HTTP/1.1的请求变换成以下:
OPTIONS * HTTP/1.1
Host: dest.com
看着可能不明显,但其中的SP都被笔者替换成了HT,并且,SP、HT能够是1到多个,头部字段中SP 、HT能够是零个。常见的web容器都是接受这种HTTP请求的。
关于这条,相关细节能够到WAF Bypass Techniques ,笔者就不细讲了。发明做者说它用这条技巧来绕过WAF(非嵌入型)对服务器上的一些目录的访问限制。 根据本文前面所说,能够知道,对于嵌入型一类的WAF,是根本不可能利用pipelining来进行绕过的——嵌入型WAF得到的数据的来源是Web容器,web容器识别出这是两个包,对于WAF也是两个包。 不过这上面的两点感受对WAF都没啥用,snort都能识别,那基本上全部WAF厂商都能识别吧。不过知道多点不亏,上面第一点在笔者某次测试中仍是体现了一点价值。
如今愈来愈多的Web容器都开始支持比较高级的协议了,正常来讲,这块不可能不出现新的安全问题的,笔者以前简单查看了HTTP/2.0 与Websocket的主体内容,未发现有什么利用点,后面也未花时间去研究,写在这里也算给本身一个备忘录。
在一个HTTP请求中,诸如json、base64这样的数据,是由后台代码调用相应的解析库来进行解析的,即使是同结构,不一样语言不一样库也可能存在一些差别。
PHP解析Base64沿袭了其一向“弱”风格,即使你的字符串含有PHP非法字符串,它也能够成功解析并处理。
测试代码:
echo base64_decode($_POST[‘test’]);
POST提交
test=M#TIzNA==
页面返回
1234
在HTTP请求体中传递JSON数据,通常状况下若是网站用的框架,则Content-Type须要指定application/json类型;若是用了三方库,如fastjson,content-type随意便可。 能够将尝试将key或vaule替换成\uxxxx的unicode字符。
POST /json.do HTTP/1.1 Host: 127.0.0.1:8081 Content-Type: application/json Content-Length: 68 {"\u006e\u0061\u006d\u0065":"'\u0072\u006f\u006f\u0074","age":"18"} HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Content-Type: text/plain;charset=ISO-8859-1 Content-Length: 44 User{name=''root', age=18, contactInfo=null}
这里的unicode关联到JSON,只是一个实际的场景,但能够本身发挥。
soap之类的协议应该也属于XML类,能够利用这类标记语言的实体编码特性。另外发送请求前考虑一下Content-Type类型。
POST /xml.do HTTP/1.1 Host: 127.0.0.1:8081 Content-Type: application/xml Content-Length: 93 <?xml version="1.0" ?> <admin> <name>"'root</name> </admin> HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Content-Type: text/plain;charset=ISO-8859-1 Content-Length: 31 Admin{name='"'root', age=null}
还有一个字符表示方式,八进制,如#十六进制的值为23,八进制表示为\43,也是一个可能的点,如在OGNL中就可使用。
sqlmap的tamper脚本中有个脚本,将’替换为%ef%bc%87,听说是UTF-8全角字符,可是这种说明没有根本地解释这个问题,笔者也不知道什么环境下产生这种利用条件。直到某一天,看到一篇文章,它们之间彷佛存在某在联系——Unicode同形字引发的安全问题,现阶段笔者也只能这样认知这个tamper脚本。 有个趣的网站,它已经整理好了,https://www.irongeek.com/homoglyph-attack-generator.php
Char | 同形 |
ᅟ ᅠ ㅤ | |
! | ! ǃ ! |
“ | ” ״ ″ " |
$ | $ $ |
% | % % |
& | & & |
‘ | ‘ ' |
( | ( ﹝ ( |
) | ) ﹞ ) |
* | * ⁎ * |
+ | + + |
, | , ‚ , |
– | – ‐ - |
. | . ٠ ۔ ܁ ܂ ․ ‧ 。 . 。 |
/ | / ̸ ⁄ ∕ ╱ ⫻ ⫽ / ノ |
0 | 0 O o Ο ο О о Օ O o |
1 | 1 I ا 1 |
2 | 2 2 |
3 | 3 3 |
4 | 4 4 |
5 | 5 5 |
6 | 6 6 |
7 | 7 7 |
8 | 8 Ց 8 |
9 | 9 9 |
IIS %,在参数中,若是%后面不是符合URL编码十六进制值,就会忽略该%符合,如id=%%20,等价于id=%20。 IIS asp 中的GET请求方式提交Body表单,后台可接收。 IIS asp的参数污染中,经过,逗号链接污染参数。 Tomcat 路径跳转中容许;符号,/..;/..;/。 PHP $_REQUEST能够接收cookie中的参数。 这块想不到更多的了…
思考一下,WAF拿到一个数据以后,在对其进行内容匹配时,是否是会将其放入一个固定大小的内存空间中,这个空间的大小是有限的。假设HTTP Request的body部分大小为2333字节,该内存大小为2000字节,那么其核心引擎在作内容匹配时,是否是先处理2000字节,在处理剩下的333字节。至于如何利用,能够发挥本身的想象。
一个是利用URL中的白名单,如图片、JS等静态资源文件。 还能够尝试利用下面这些头部字段
X-Forwarded-For: 127.0.0.1
X-Client-IP: 127.0.0.1
Client-IP: 127.0.0.1
另外能够尝试修改Host头部字段。
前面所讲的都是输入角度,这里咱们谈谈输出角度。咱们在Request中发送Pyaload,会但愿从Response的回显或基于时间这些信息通道来获取Payload执行成功后的相关信息。若是存在某种WAF,检测到Response中的回显数据存在敏感信息,Resonse响应包可能就被阻断掉了。(固然,除了基本的回显数据通道,还有基于时间的数据通道)
遇到这种状况,应对的方法之一就是使用OOB思想来绕过。如XXE OOB、SQL注入OOB、命令注入OOB,等等。
假如页面可能有敏感数据返回,而当前攻击场景又利用不了OOB,你能够尝试使用Range方法来绕过防火墙。 普通请求与页面结果:
POST /test/test.php HTTP/1.1 Host: 192.168.17.138 Content-Type: application/x-www-form-urlencoded Content-Length: 9 Range: bytes=10-30 user=root HTTP/1.1 200 OK Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j PHP/5.2.17 Content-Length: 42 Content-Type: text/html SELECT password from user where user = ''
添加了range,请求获取返回页面0到10的数据:
POST /test/test.php HTTP/1.1 Host: 192.168.17.138 Content-Type: application/x-www-form-urlencoded Content-Length: 9 Range: bytes=0-10 user=root HTTP/1.1 206 Partial Content Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j PHP/5.2.17 Content-Range: bytes 0-10/394 Content-Length: 11 Content-Type: text/html SELECT pass
添加了range,请求获取返回页面10到30的数据:
POST /test/test.php HTTP/1.1 Host: 192.168.17.138 Content-Type: application/x-www-form-urlencoded Content-Length: 9 Range: bytes=10-30 user=root HTTP/1.1 206 Partial Content Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j PHP/5.2.17 Content-Range: bytes 10-30/394 Content-Length: 21 Content-Type: text/html sword from user where
Range方式应该是全部Web容器默认支持的,这个东西仍是有点意思,有点做用。
看CVE时发现的,3whs bypass ids
Attack scenario TCP flow scheme: Client -> [SYN] [Seq=0 Ack= 0] -> Evil Server Client <- [SYN, ACK] [Seq=0 Ack= 1] <- Evil Server Client <- [PSH, ACK] [Seq=1 Ack= 1] <- Evil Server # Injection before the 3whs is completed Client <- [FIN, ACK] [Seq=83 Ack= 1] <- Evil Server Client -> [ACK] [Seq=1 Ack= 84] -> Evil Server Client -> [PSH, ACK] [Seq=1 Ack= 84] -> Evil Server
在三次握手未完成以前,服务端返回了数据,能够形成HTTP流量检测的绕过,该种攻击场景多是被用于挂马、钓鱼之类的。在连接中做者给出了对应的PCAP包,能够下载来看看,算是涨见识。 在传输层这里,还有一些简单而具有实际意义的操做,好比将一个TCP报文分片成不少不少份,一份几个字节,十几个字节,对端服务器能正常接收,而对非嵌入型的WAF就是一个考验;还有,咱们知道,TCP是可靠的协议,那么咱们再将这些报文进行一个合适的乱序,那么是否也可行。
对于非嵌入型WAF,在解析SSL数据时,须要该SSL通讯端服务器的密钥(非对称)。客户端在与Web服务器进行HTTPS通讯时,协商SSL的加密方式能够有不少种,若是其中有一种加密方式刚好是WAF没法识别的,那么WAF就只能睁眼瞎了。 Bypassing Web-Application Firewalls by abusing SSL/TLS
笔者以前了解到,中小公司的防火墙的流量处理能力是很弱的,因此DOS确实可行,算是最后的方案。
其余说明,RFC7230对文章中所说的RFC2616的描述未发生修改。 本文参考资料汇总以下
原文连接:对过WAF的一些认知
RCF2616:https://tools.ietf.org/html/rfc2616
Bypassing Web-Application Firewalls by abusing SSL/TLS:https://0x09al.github.io/waf/bypass/ssl/2018/07/02/web-application-firewall-bypass.html
WAF Bypass Techniques https://2018.appsec.eu/presos/HackerWAF-Bypass-TechniquesSoroush-Dalili_AppSecEU2018.pptx
Application Security Weekly: Reverse Proxies Using Weblogic, Tomcat, and Nginx:https://www.acunetix.com/blog/web-security-zone/asw-reverse-proxies-using-weblogic-tomcat-and-nginx/
Protocol-Level Evasion of Web Application Firewalls https://media.blackhat.com/bh-us-12/Briefings/Ristic/BHUS12RisticProtocolLevelSlides.pdf
Chunked HTTP transfer encoding:https://swende.se/blog/HTTPChunked.html
Impedance Mismatch and Base64:https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/impedance-mismatch-and-base64/
HTTP 协议中的 Transfer-Encoding:https://imququ.com/post/transfer-encoding-header-in-http.html
浅谈json参数解析对waf绕过的影响:https://xz.aliyun.com/t/306
3whs bypass ids:https://www.exploit-db.com/exploits/44247/
Web Application Firewall (WAF) Evasion Techniques:https://medium.com/secjuice/waf-evasion-techniques-718026d693d8
BypassWAF新思路(白名单):https://www.chainnews.com/articles/774551652625.htm
利用分块传输吊打全部WAF:https://www.anquanke.com/post/id/169738
HTTP Request Smuggling:https://www.cgisecurity.com/lib/HTTP-Request-Smuggling.pdf