- http 1.1 (应用层)
- 特性:
- keepalive
- 建立一次tcp连接后,并不会把连接关闭(完成tcp三次握手)
- pipline
- 可在同一个请求的head(报头)写入两个http请求包
- keepalive
- HTTP协议中的Transfer-Encoding:HTTP 协议中的 Transfer-Encoding | JerryQu 的小站
- HTTP请求走私漏洞的产生:大多数 HTTP 请求走私漏洞的出现是因为 HTTP 规范提供了两种不同的方式来指定请求的结束位置:Content-Length标头和Transfer-Encoding标头
- 漏洞类型
- 如何执行HTTP请求走私攻击
- 请求走私攻击涉及将Content-Length标头和Transfer-Encoding 标头放入单个 HTTP 请求并对其进行操作,以便前端和后端服务器以不同的方式处理请求。完成此操作的确切方式取决于两个服务器的行为:
- CL.TE:前端服务器使用Content-Length头部,后端服务器使用Transfer-Encoding头部。
- TE.CL:前端服务器使用Transfer-Encoding头部,后端服务器使用Content-Length头部。
- TE.TE:前端服务器和后端服务器都支持Transfer-Encoding头部,但是可以通过某种方式混淆头部来诱导其中一个服务器不处理它。
- 请求走私攻击涉及将Content-Length标头和Transfer-Encoding 标头放入单个 HTTP 请求并对其进行操作,以便前端和后端服务器以不同的方式处理请求。完成此操作的确切方式取决于两个服务器的行为:
- 基本 CL.TE 漏洞
- 前端服务器使用Content-Length标头,后端服务器使用Transfer-Encoding标头
- 前端服务器处理Content-Length标头并确定请求正文长度为 13 个字节,直到SMUGGLED. 该请求被转发到后端服务器。
- 后端服务器处理Transfer-Encoding标头,因此将消息正文视为使用分块编码。它处理第一个块,它被声明为零长度,因此被视为终止请求。接下来的字节 ,SMUGGLED未处理,后端服务器会将它们视为序列中下一个请求的开始。
- 发包时注意要有:Transfer-Encoding: chunked(定义选用的传输编码格式)
- 使用 Burp Repeater,两次发出以下请求:
- 第二个响应应该说:Unrecognized method GPOST:
- 效果
- 前端服务器使用Content-Length标头,后端服务器使用Transfer-Encoding标头
- TE.CL 漏洞
- 前端服务器使用Transfer-Encoding标头,后端服务器使用Content-Length标头:要使用 Burp Repeater 发送此请求,首先需要进入 Repeater 菜单并确保未选中“Update Content-Length”选项。需要\r\n\r\n在最后的0
- 前端服务器处理Transfer-Encoding标头,因此将消息正文视为使用分块编码。它处理第一个块,它被声明为 8 个字节长,直到下面一行的开头SMUGGLED。它处理被声明为零长度的第二个块,因此被视为终止请求。该请求被转发到后端服务器。
- 后端服务器处理Content-Length标头并确定请求正文的长度为 3 个字节,直到8. 以下以 开头的字节SMUGGLED未处理,后端服务器会将它们视为序列中下一个请求的开始。
- 前端服务器使用Transfer-Encoding标头,后端服务器使用Content-Length标头:要使用 Burp Repeater 发送此请求,首先需要进入 Repeater 菜单并确保未选中“Update Content-Length”选项。需要\r\n\r\n在最后的0
- TE.TE 行为:混淆 TE 标头
- 这里,前端和后端服务器都支持Transfer-Encoding标头,但可以通过以某种方式混淆标头来诱导其中一台服务器不处理它。
- 可能有无数种方法来混淆Transfer-Encoding标题。例如:
- 每一种都涉及与 HTTP 规范的微妙偏离。实现协议规范的实际代码很少绝对精确地遵守它,并且不同的实现通常会容忍来自规范的不同变化。要发现 TE.TE 漏洞,需要找到Transfer-Encoding报头的一些变体,以便只有前端或后端服务器之一处理它,而另一台服务器忽略它。
- 根据可以诱导不处理混淆Transfer-Encoding标头的是前端还是后端服务器,攻击的其余部分将采用与已经描述的 CL.TE 或 TE.CL 漏洞相同的形式。
- 如何执行HTTP请求走私攻击
- 特性:
- http2
- HTTP/2标准于2015年5月以RFC 7540正式发表,基于SPDY协议。根据W3Techs的数据,截至2021年7月,全球有46.0%的网站支持了HTTP/2。
- HTTP/2协议相对于HTTP/1.1在性能上有了很大的提升,主要具有以下新特性:
- 二进制分帧
- 请求与响应复用
- 服务端推送
- 头部压缩
- 攻击点
- 对于这些新特性,都有相对应的攻击点。目前大多数CDN厂商都支持HTTP/2,但是很多后端服务并不支持,所以CDN需要做一个HTTP/2到HTTP/1.x的转换,对于头部压缩特性,需要进行解压,所以导致带宽放大攻击,具体可以看HTTP协议攻击
- HTTP/2降级走私
- 产生原因
- 在 HTTP/1 中,每个消息主体的长度通过内容长度(Content-Length)或传输编码(Transfor-Encoding)header表示
- 在 HTTP/2 中,这些header是多余的,因为使用二进制流进行传输,没有文本的概念,消息的内容都是由数据帧(Data Frame)进行传递,每个帧中的内容的长度,是有Length进行记录的
- 在HTTP/2转换为HTTP/1.x的降级过程中,就会出现新的问题:前端服务使用HTTP/2协议,使用协议中内在的message的Length,而后端服务却使用HTTP/1.1协议,可以接收到含有CL或者TE的请求,此时就会导致出现HTTP/2协议的走私可能
- 案例:
- H2.CL
- 以Netflix为例,发送此http/2数据
- 对于后端服务来说,这直接导致了走私漏洞,相关漏洞信息可以查看CVE-2021-21295。那么对于完全不需要Content-Length来进行标识请求体长度的HTTP/2协议来说,为什么会出现这个问题呢?
- RFC7540编写的十分清晰,HTTP/2请求和响应可以包括Content-Length头,但是对于Content-Length的值和DATA frame的长度不一致的情况,应该视为格式错误。而且第三段明确规定,处理 HTTP 请求或响应的中介(即任何中介不充当隧道)不得转发格式错误的请求或响应。
- 在转换成http/1.1后,内容成为了
-
POST /n HTTP/1.1 Host: www.netflix.com Content-Length: 4 abcdGET /n HTTP/1.1 Host: 02.rs?x.netflix.com Foo: bar
-
- 以Netflix为例,发送此http/2数据
- H2.TE
- 此漏洞发生在AWS Application Load Balance中
- 发送数据包为
- 后端服务接受到数据包为
-
POST /identity/XUI/ HTTP/1.1 Host: id.b2b.oath.com Content-Length: 68 Transfer-Encoding: chunked 0 GET /oops HTTP/1.1 Host: psres.net Content-Length: 10 x=
-
- 这种走私类型就类似于HTTP/1.1中的CL-TE。
- 这种漏洞的产生,也是中间件对于Transfor-Encoding的处理出现了错误导致,对于HTTP/2来说,一个TCP连接就可以完成一个客户端和服务端之间持续的数据的传送,所以对于Connection系列字段都是不需要的,所有请求与响应的标识是通过Stream ID来进行的。
- RFC7540规定,端点不得生成包含特定于连接的标头的 HTTP/2 消息
- 领域;任何包含特定连接头的消息必须被视为格式错误,唯一的例外是 TE 头,可以存在于 HTTP/2 请求中,但其不得包含任何“trailers”以外的取值。当然如果中间件需要处理从HTTP/1.x到HTTP/2的转换,是应该删除相关连接头,Keep-Alive, Proxy-Connection, Transfer-Encoding, and Upgrade,即使他们没有被标识为连接头字段。
- H2.CL
- H2.TE通过http header值注入
- 即使中间件正确处理了Transfor-Encoding头,将之删除或者直接返回错误,但是依旧可以参照http/1.1的header注入,来进行走私。
- 在中间件验证HTTP/2数据包头部是否含有Transfor-Encoding的情况下,直接不把Transfor-Encoding作为一个完整的header字段,而是通过r\n注入在header中的字段值中,这样就绕过了上文RFC规定的验证。
- 如果通过转换,其HTTP/1.1请求为
-
POST / HTTP/1.1\r\n Host: start.mozilla.org\r\n Foo: b\r\n Transfer-Encoding: chunked\r\n Content-Length: 77\r\n \r\n 0\r\n \r\n GET / HTTP/1.1\r\n Host: evil-netlify-domain\r\n Content-Length: 5\r\n \r\n x=
- 这样依旧可以造成走私。
-
- 当然在HTTP/2中是二进制流协议,并不像HTTP/1.x需要\r\n来进行每一行的标识。然而当把这些可以在HTTP/1.x中作为标识的字符用在HTTP/2中,在转换过程中,就会让其发挥作用,导致安全问题。RFC也考虑到此问题
- 即使中间件正确处理了Transfor-Encoding头,将之删除或者直接返回错误,但是依旧可以参照http/1.1的header注入,来进行走私。
-
- 如果这些字符如CRLF,0x0,被逐一解析,可能被攻击者利用,所以规定任何请求或响应包含头字段值中不允许的字符必须被视为格式错误,当然很明显并不是多有中间件都遵守此规定。
- H2.TE 通过header name注入
- 上文提到,通过在header字段中,添加\r\n来进行Transfor-Encoding的注入,从而绕过HTTP/2协议中不允许Transfor-Encoding字段的规定,那么可以在header name中也实现注入,这种情况就需要另外一个危险字符:
-
- 转换HTTP/1.1后,数据包为
-
GET / HTTP/1.1 foo: bar transfer-encoding: chunked host: ecosystem.atlassian.net
-
- 依旧可以使用Transfor-Encoding来进行走私。
- 转换HTTP/1.1后,数据包为
- H2.TE 通过请求行注入
- 如果中间件只是修复了普通Header中关于危险字符的过滤,那么对于foo或者Transfor-Encoding字段来说,并不能使用,所以作者使用伪标头来进行注入,在HTTP/2中,所有标头字段名称均为小写,请求行拆分成各个:method、:scheme、:authority 和 :path 伪标头字段,以:method为例
- 将走私请求直接注入到method中
-
GET / HTTP/1.1 transfer-encoding: chunked x: x /ignored HTTP/1.1 Host: eco.atlassian.net
-
- 如果中间件只是修复了普通Header中关于危险字符的过滤,那么对于foo或者Transfor-Encoding字段来说,并不能使用,所以作者使用伪标头来进行注入,在HTTP/2中,所有标头字段名称均为小写,请求行拆分成各个:method、:scheme、:authority 和 :path 伪标头字段,以:method为例
- 所以中间件对于header中危险字符的过滤,应该把所有字段都进行处理。
- H2.X 通过请求拆分
- 既然可以注入\r\n,作者又直接将整个走私请求注入到header处,以达成攻击。
- 这种方式,更加简单粗暴,只要中间件在转换过程中,逐一识别危险字符\r\n,那么转换成的HTTP/1.1数据就为
-
GET / HTTP/1.1 Foo: bar Host: ecosystem.atlassian.net GET /robots.txt HTTP/1.1 X-Ignore: x Host: ecosystem.atlassian.net\r\n \r\n
-
- 这种走私,不需要使用Transfor-Encoding编码,也不需要body和POST方法。
- 既然可以注入\r\n,作者又直接将整个走私请求注入到header处,以达成攻击。
- 产生原因
- 检测工具:
- http请求走私检测:GitHub - anshumanpattnaik/http-request-smuggling: HTTP Request Smuggling Detection Tool
- http2:https://github.com/BishopFox/h2csmuggler
- http2参考文章:HTTP/2降级走私攻击_黑客技术 (hackdig.com) 【技术向】HTTP/1与HTTP/2(H2C)走私攻击 (kanxue.com)