![Burp+HTTP2攻击面分析 Burp+HTTP2攻击面分析]()
截至到目前根据Cloudflare统计,HTTP2.0使用量已经超过了HTTP1.1,但HTTP2.0也有未完善的点,更多的可能是个过渡,所以目前HTTP3.0的使用量一直在呈现上升趋势,但当下HTTP2.0还是占据大头。
这里简单记录一下H2和H1的区别点,便于后续攻击面分析的理解,大体来说主要分为:数据格式、多路复用、头部压缩、服务端推送等。
数据格式:H1的数据是文本格式,方便阅读,但是不利于传输和解析,而H2进行了优化,采用的是二进制格式。
多路复用:H1接收响应时会单个单个的进行接收,容易造成阻塞问题,H2进行了优化,可并发的请求和响应。
头部压缩:H1的数据包头部会包含大量的头部字段,携带信息太多,H2进行了优化,会对头部进行压缩处理。
服务端推送:H1中要请求一个网页,网页的相关静态资源都需要客户端去逐个请求获取,而H2中当客户端访问一个HTML时,服务端会把这个HTML涉及到的相关资源都主动推给客户端。
上面也说了,H2的传输格式是二进制,那么就会涉及到两个问题:1,如何读取包内容。2,如何识别包头中的各个字段。
先看如何读取包内容,在H1中读取数据包内容是通过头部的Content-Length和Transfer-Encoding来确定的具体要读多少内容,而在H2中简单理解就是H2会把数据包的头和数据内容部分分别压缩为数据帧,数据帧的帧头中包含了要读取内容的长度。
那么如何识别包头中的各个字段,原理和读取数据包内容是一样的,不过这里需要提的是伪标头的概念,数据头在传输中也是二进制,但为了开发调试和测试,会把头内容以可读的形式展现出来,具体涉及到5个部分,说明如下:
只有这5个伪标头,它们有特殊的含义,为了和普通标头区分开,H2指定伪标头前面用冒号标识。
H2降级大概流程是这样的,用户连接服务器协商,服务器支持H2,那么客户端就会以H2协议去发送请求,但是请求到前端服务器(前端服务器转发比如nginx,后端的服务器处理比如apache)的时候,它可能默认会对请求进行降级,也或者是为了保证服务器能正确处理请求(以前的服务器可能不支持H2),会进行转换操作,把H2转为H1,这种情况就叫做HTTP2降级。
或者是请求发送的H1,然后我们手动改为H2,看是否可以正常响应,判断前端服务器是否会有降级操作。后续的大多攻击面都会基于降级展开。
在H2降级的情况下,请求走私问题更容易发生,比如我们用H2发送,数据包内容如下:
POST / HTTP/2
Host: example.com
Content-Length: 0
GET / HTTP/1.1
Host: xxx.com
Content-Length: 5
x=1
我们发送H2时,因为它的内容长度不是基于Content-Length字段的,所以整个内容都会发出去,而前端服务器如何降级的话,转为了H1,那Content-Length就生效了,长度为0,就会导致GET请求那个包留在服务器,认为还没发完,就会和下个用户的请求进行合并,造成了数据走私问题,这种类型叫H2.CL。
还有一种情况,不是Content-Length,而是Transfer-encoding,比如下面这个数据包:
POST / HTTP/2
Host: example.com
Content-Length: 0
Transfer-encoding: chunked
0
GET / HTTP/1.1
Host: xxx.com
还是H2整个包发送给后端,前端服务器会进行降级,转为H1,因为是通过Transfer-encoding来读取内容,遇到0则结束,就会导致GET那部分留在服务端,认为没接收完,等待下个请求来了进行拼接,造成了走私问题,这种类型叫做H2.TE。
客户端和服务端通信之所以用HTTP2,在于它们握手期间,服务器会发送一个ALPN的标识,意思代表我支持HTTP2,但有些服务器可能没有正确配置这个ALPN的支持,导致握手期间以为服务器只支持HTTP1.1,这种情况下可以在菜单栏Repeater下选中Allow HTTP/2 ALPN override选项,即后续测试哪怕服务器没有发ALPN标识,Burp也会认为对方支持HTTP2.
之后测试时,只需要在右侧的Inspector下的Request attributes中选中HTTP/2即可,如下图。
如果服务器对H2.CL和H2.TE做了防护,比如会检测标头,那么此时则可以利用H2的二进制特性来结合CRLF进行绕过尝试。
首先把请求发到Repeater,然后在右侧的Inspector展开Request attributes,确保请求协议为HTTP/2。
然后还是Inspector,找到Request header,新添加一个请求头,名字随意起,值的话需要添加个回车换行,然后跟Transfer-Encoding: chunked,添加回车换行组合键是Shift+Enter。
原理即将CL或TE添加到value值中来尝试绕过检测。
确认后请求的头就看不到了,只能看到请求体,如下图。
这种情况Burp叫做kettled请求,意思就是说用HTTP1的语法修改了HTTP2的请求头,如果添加了回车换行,则会显示kettled,因为回车换行在H1中是无法显示的,代表了特殊含义,此时直接点击Send就可以继续测试,不影响。
Burp也正在优化,后续说是会尽量以友好的界面展示。
那我们来分析一下,首先是H2请求,头中包含了aaa头,值是bbb回车换行Transfer-Encoding,因为服务器有检测机制,所以通过这种形式把TE放到值上来进行绕过,后端进行降级处理后,回车换行生效,导致了TE标头生效,最后造成走私问题。
利用这个机制也可以造成响应中毒问题,比如添加一个头,内容如下:
bbbrn
rn
GET / HTTP/1.1rn
Host: example.com
那么降级后相当于把请求拆成了两个,而我们只能收一个响应的情况下,这个example的响应就留在了服务端,那下一个用户请求时,请求的其它内容,但它收到的响应确是我们刚才遗留的example的响应,此时攻击者如果立马再发一个请求的话,则会收到刚才受害者的请求信息。
上面说的CRLF注入就是拆分的效果,即走私一个完整的请求,但是通过在标头的值中来添加CL或TE实现的,还有一种拆分方法,可以不借助CL和TE,直接拆分,比如下面的数据包:
:method GET
:path /
:authority example.com
test
testrn
rn
GET /admin HTTP/1.1rn
Host: sectest.com
这种方法如果生效,那么服务器也会成功接收到两个请求。
在HTTP2的伪标头中:authority用来表示请求的地址,但添加Host有可能会生效,所以可以尝试测试主机头攻击。
:method GET
:path /
:authority example.com
Host: attacker.com
在HTTP2的伪标头中:scheme用来代表协议,比如http、https,但测试时可以输入其它内容,比如一个恶意地址,示例如下:
:method GET
:path /xxx.js
:authority test.example.com
:scheme http://xxx.com/xxx?
那么后端收到数据包时,拼接起来所要访问的请求就变成了:
http://xxx.com/xxx?://test.example.com
利用这种机制可以测试缓存中毒或者SSRF,这种情况不需要HTTP2降级也可以测试。
1,服务器配置,如果要使用H2,则配置端到端的情况,避免前端服务器的降级操作。
2,如果目前需要支持H1,则建议对包头的值和内容做过滤,例如换行符,冒号,空格等。
https://portswigger.net/research/http2
原文始发于微信公众号(aFa攻防实验室):Burp+HTTP2攻击面分析
评论