目录

HTTP报文包体的解析

Transfer-Encoding

Charset

溢量数据

HTTP协议兼容性

HTTP请求行种的空格

HTTP 0.9+Pipelining

Websocket、HTTP/2.0

高层数据

base64

Unicode JSON

实体编码 XML

八进制

同形字

容器语言特性

匹配缓冲区大小固定

白名单

输出角度

OOB

Range

其他参考

传输层

SSL层

DOS

结语


本文主要从绕过WAF过程中需要注意的角色和点出发,尝试理解它们的运作,构建一个简单的知识框架。

首先,WAF分为非嵌入型WAF和嵌入型WAF,非嵌入型WAF指的是硬WAF、云WAF、虚拟机WAF之类的;而嵌入型WAF指的是Web容器模块类型的WAF、代码层WAF。非嵌入型WAF对Web流量的解析完全是靠自身的,而嵌入型WAF拿到的Web数据是已经被解析加工好的。所以非嵌入型的受攻击机面还涉及到其他层面,而嵌入型WAF从Web容器模块类型WAF、代码层WAF往下走,其对抗畸形报文、扫操作绕过的能力越来越强。当然,在部署维护成本方面,也是越高的。

有些WAF设置的是针对域名的防护,有些时候,我们尝试将域名改成ip地址可以绕过WAF的防护。

HTTP报文包体的解析

我们先来探讨一个问题。HTTP请求的服务器在接收到该请求时,会关心哪些头部字段,以及如何根据这些头部字段做出对Request-body 进行相应的解析处理。说实话,要搞清这些东西,最好还是查看web容器的源码,但笔者现在还没做到这一步,在这里仅能根据自身的认知提及一些头部字段。这些头部字段的关系,笔者认为可以总结为如下:

Transfer-Encoding(Content-Encoding(Content-Type(charset(data))))

Transfer-Encoding

关于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

在HTTP协议层面绕过WAF

HTTP 协议中的 Transfer-Encoding

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

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(图片绕过)

HTTP协议兼容性

HTTP请求行种的空格

在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请求的。

HTTP 0.9+Pipelining

关于这条,相关细节可以到WAF Bypass Techniques,笔者就不细讲了。发明作者说它用这条技巧来绕过WAF(非嵌入型)对服务器上的一些目录的访问限制。 根据本文前面所说,可以知道,对于嵌入型一类的WAF,是根本不可能利用pipelining来进行绕过的——嵌入型WAF获得的数据的来源是Web容器,web容器识别出这是两个包,对于WAF也是两个包。 不过这上面的两点感觉对WAF都没啥用,snort都能识别,那基本上所有WAF厂商都能识别吧。不过知道多点不亏,上面第一点在笔者某次测试中还是体现了一点价值。

Websocket、HTTP/2.0

现在越来越多的Web容器都开始支持比较高级的协议了,正常来说,这块不可能不出现新的安全问题的,笔者之前简单查看了HTTP/2.0 与Websocket的主体内容,未发现有什么利用点,后面也未花时间去研究,写在这里也算给自己一个备忘录。

高层数据

在一个HTTP请求中,诸如json、base64这样的数据,是由后台代码调用相应的解析库来进行解析的,即便是同结构,不同语言不同库也可能存在一些差异。

base64

PHP解析Base64沿袭了其一贯“弱”风格,即便你的字符串含有PHP非法字符串,它也可以成功解析并处理。

测试代码:

echo base64_decode($_POST[‘test’]);

POST提交

test=M#TIzNA==

页面返回

1234

Unicode JSON

在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,只是一个实际的场景,但可以自己发挥。

实体编码 XML

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>&quot;&apos;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

遇到这种情况,应对的方法之一就是使用OOB思想来绕过。如XXE OOB、SQL注入OOB、命令注入OOB,等等。

Range

假如页面可能有敏感数据返回,而当前攻击场景又利用不了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是可靠的协议,那么我们再将这些报文进行一个合适的乱序,那么是否也可行。

SSL层

对于非嵌入型WAF,在解析SSL数据时,需要该SSL通信端服务器的密钥(非对称)。客户端在与Web服务器进行HTTPS通信时,协商SSL的加密方式可以有很多种,如果其中有一种加密方式恰好是WAF无法识别的,那么WAF就只能睁眼瞎了。 Bypassing Web-Application Firewalls by abusing SSL/TLS

DOS

笔者之前了解到,中小公司的防火墙的流量处理能力是很弱的,所以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

如何绕过WAF的更多相关文章

  1. 深入理解SQL注入绕过WAF和过滤机制

    知己知彼,百战不殆 --孙子兵法 [目录] 0x0 前言 0x1 WAF的常见特征 0x2 绕过WAF的方法 0x3 SQLi Filter的实现及Evasion 0x4 延伸及测试向量示例 0x5 ...

  2. 深入了解SQL注入绕过waf和过滤机制

    知己知彼百战不殆 --孙子兵法 [目录] 0x00 前言 0x01 WAF的常见特征 0x02 绕过WAF的方法 0x03 SQLi Filter的实现及Evasion 0x04 延伸及测试向量示例 ...

  3. 深入理解SQL注入绕过WAF与过滤机制

    知己知彼,百战不殆 --孙子兵法 [目录] 0x0 前言 0x1 WAF的常见特征 0x2 绕过WAF的方法 0x3 SQLi Filter的实现及Evasion 0x4 延伸及测试向量示例 0x5 ...

  4. 黑客是怎样绕过WAF之三重防护绕过讲解

    什么是WAF Web Application Firewall 通过执行一系列针对HTTP/HTTPS的安全策略来防御对Web应用的攻击. 目前主要有单设备WAF与云WAF WAF的现状 1.太多数W ...

  5. 在SQL注入中利用MySQL隐形的类型转换绕过WAF检测

    web应用一般采用基于表单的身份验证方式(页面雏形如下图所示),处理逻辑就是将表单中提交的用户名和密码传递到后台数据库去查询,并根据查询结果判断是否通过身份验证.对于LAMP架构的web应用而言,处理 ...

  6. 使用sqlmap中tamper脚本绕过waf

    使用sqlmap中tamper脚本绕过waf 刘海哥 · 2015/02/02 11:26 0x00 背景 sqlmap中的tamper脚本来对目标进行更高效的攻击. 由于乌云知识库少了sqlmap- ...

  7. 通过HTTP参数污染绕过WAF拦截 (转)

    上个星期我被邀请组队去参加一个由CSAW组织的CTF夺旗比赛.因为老婆孩子的缘故,我只能挑一个与Web漏洞利用相关的题目,名字叫做”HorceForce”.这道题价值300点.这道题大概的背景是,你拥 ...

  8. sqlmap注入之tamper绕过WAF脚本列表

    本文作者:i春秋作者——玫瑰 QQ2230353371转载请保留文章出处 使用方法--tamper xxx.py apostrophemask.py用UTF-8全角字符替换单引号字符 apostrop ...

  9. SQL注入9种绕过WAF方法

    SQL注入9种绕过WAF方法 0x01前言 WAF区别于常规 防火墙 是因为WAF能够过滤特定Web应用程序的内容,而常规防火墙则充当服务器之间的防御门.通过检查HTTP的流量,它可以防御Web应用安 ...

  10. 用最短的payload绕过WAF(入门)

    本文作者:jishuzhain <font color=green>想绕过一个WAF,我们可以用最短的payload来做,这里只是基础示例,望各位大佬勿喷,小弟在此谢过.</font ...

随机推荐

  1. 【python+selenium的web自动化】- 控制浏览器的常用操作

    如果想从头学起selenium,可以去看看这个系列的文章哦! https://www.cnblogs.com/miki-peng/category/1942527.html 前言 ​ 本文主要介绍se ...

  2. 循环单链表定义初始化及创建(C语言)

    #include <stdio.h> #include <stdlib.h> /** * 含头节点循环单链表定义,初始化 及创建 */ #define OK 1; #defin ...

  3. 全真教程:Windows环境Jupyter Notebook安装、运行和工作文件夹配置

    全真教程:Windows环境Jupyter Notebook安装.运行和工作文件夹配置 @ 目录 全真教程:Windows环境Jupyter Notebook安装.运行和工作文件夹配置 一.Jupyt ...

  4. MySql多表查询_事务_DCL(资料三)

    今日内容 1. 多表查询 2. 事务 3. DCL 多表查询: * 查询语法: select 列名列表 from 表名列表 where.... * 准备sql # 创建部门表 CREATE TABLE ...

  5. wireshark如何抓取分析https的加密报文

    [问题概述] https流量基于ssl/tls加密,无法直接对报文进行分析. [解决方案] 方案1 -- 利用"中间人攻击"的代理方式抓包分析.整个方案过程比较简单,这里不赘述,大 ...

  6. Lzzy高级语言程序设计之while循环

    public class Mq2 { public static void main(String[]args) { int b = 3; while (b < 7) { System.out. ...

  7. JAVA面试题:输出100以内所有的素数

    转载:https://www.cnblogs.com/onway/archive/2012/11/15/2771912.html Java输出1-100中所有的素数 很多人笔试时都会遇到这个问题,小农 ...

  8. Win 10 下Pipenv源码安装 odoo12

    因为,本身电脑已经安装odoo8,9,10等odoo的版本,当时,没有考虑是直接是统一的环境很配置. 现在,在odoo11的环境下,需要Python 3的语言环境可以很好地支持odoo11的功能,所以 ...

  9. java IO流文件拷贝文件(字节流标准写法)

    public static void copyFile(String srcPath, String destPath) { FileInputStream fis = null; FileOutpu ...

  10. 11、MyBatis教程之动态SQL

    12.动态SQL 1.介绍 什么是动态SQL:动态SQL指的是根据不同的查询条件 , 生成不同的Sql语句. 官网描述: MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或 ...