一、漏洞简介

1.1 漏洞背景

Nginx 的 DNS 解析器(resolver)模块用于处理异步 DNS 查询,常见于反向代理、负载均衡等场景。2021 年 5 月,安全研究人员发现了该模块在处理特制 DNS 响应时存在堆溢出漏洞。

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

项目 内容
漏洞编号 CVE-2021-23017
危害等级 HIGH / 7.7
漏洞类型 漏洞 1: - DNS 解析器 1 字节堆溢出
披露时间 2021-06-01
影响组件 Nginx 重点安全
  • CVE 编号:CVE-2021-23017
  • 危害等级:中等(Medium)
  • CVSS 评分:CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H(5.9)
  • 漏洞类型:堆溢出(1 字节覆盖)
  • 潜在影响:导致 worker 进程崩溃,或潜在的远程代码执行

补充核验信息:公开时间:2021-06-01;NVD 评分:7.7(HIGH);CWE:CWE-193。

二、影响范围

2.1 受影响的版本

  • Nginx 0.6.18 - 1.20.0

2.2 不受影响的版本

  • Nginx 1.21.0 及以上
  • Nginx 1.20.1 及以上

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

  1. 配置文件中使用了 resolver 指令
  2. 攻击者能够伪造来自 DNS 服务器的 UDP 数据包(例如:中间人攻击、DNS 劫持、控制 DNS 服务器)

三、漏洞详情与原理解析

3.1 漏洞触发机制

Nginx 的 DNS 解析器在解析 DNS 响应时,对 DNS 名称压缩指针的验证不够严格。攻击者可以通过构造恶意的 DNS 响应包,利用名称压缩机制触发 1 字节的堆溢出。

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

漏洞代码位置src/core/ngx_resolver.c

问题根因: 在处理 DNS 响应中的名称解析时,ngx_resolver_copy() 函数在计算目标缓冲区大小时存在整数溢出错误。当处理特制的 DNS 名称压缩指针时,可能导致 1 字节越界写入。

关键代码片段(简化):

/* 漏洞版本的问题代码 */
n = *src++;  /* 读取名称长度 */
...
if (n != 0) {
    if (dst != NULL) {
        *dst++ = (u_char) n;  /* 写入长度字节 */
        ngx_memcpy(dst, src, n);  /* 复制名称内容 */
    }
    dst += n;  /* 指针前移 - 问题在这里!没有检查边界 */
}

修复补丁(patch.2021.resolver.txt):

/* 修复版本 - 添加了边界检查 */
if (dst + n > last) {
    return NGX_ERROR;  /* 防止越界写入 */
}

四、漏洞复现(可选)

4.1 环境搭建

# 使用 Docker 构建受影响版本
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y build-essential libpcre3-dev zlib1g-dev
RUN wget http://nginx.org/download/nginx-1.20.0.tar.gz && \
    tar -xzf nginx-1.20.0.tar.gz && \
    cd nginx-1.20.0 && \
    ./configure && make && make install

# 配置文件添加 resolver
# nginx.conf:
# http {
#     resolver 192.168.1.100;  # 指向攻击者控制的 DNS 服务器
#     ...
# }

4.2 PoC 演示与测试过程

#!/usr/bin/env python3
# 简化的 PoC - 恶意 DNS 响应构造
import socket
import struct

def craft_malicious_dns_response():
    # DNS 响应头部
    header = b'\x00\x01'  # Transaction ID
    header += b'\x81\x80'  # Flags: response
    header += b'\x00\x01'  # Questions: 1
    header += b'\x00\x01'  # Answers: 1
    header += b'\x00\x00'  # Authority RRs
    header += b'\x00\x00'  # Additional RRs

    # 恶意名称压缩指针 - 触发溢出
    # 构造超出缓冲区边界的压缩指针
    malicious_name = b'\xc0\x0c'  # 压缩指针指向偏移 0x0c
    malicious_name += b'\xff\xff'  # 恶意数据

    # 完整的 DNS 响应
    response = header + malicious_name

    return response

# 发送恶意响应(需要中间人位置)
# 注意:仅在研究环境中使用

测试结果: - Nginx worker 进程崩溃(Segmentation Fault) - 在某些情况下可能触发代码执行

五、修复建议与缓解措施

5.1 官方版本升级建议

# 立即升级到安全版本
# 下载并编译 Nginx 1.20.1 或更高版本
wget http://nginx.org/download/nginx-1.20.1.tar.gz
tar -xzf nginx-1.20.1.tar.gz
cd nginx-1.20.1
./configure && make && make upgrade

或使用补丁:

# 对现有版本打补丁
cd nginx-1.20.0
wget http://nginx.org/download/patch.2021.resolver.txt
patch -p1 < patch.2021.resolver.txt
make && make upgrade

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

  1. 限制 DNS 服务器信任nginx # 仅使用可信的 DNS 服务器 resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 5s;

  2. 使用防火墙规则bash # 限制来自 DNS 服务器的 UDP 流量 iptables -A INPUT -p udp --source 8.8.8.8 --sport 53 -j ACCEPT iptables -A INPUT -p udp --dport 53 -j DROP

  3. 禁用 resolver(如果不需要)nginx # 注释掉 resolver 配置 # resolver 192.168.1.1;

六、参考信息 / 参考链接

6.1 官方安全通告

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

6.2 其他技术参考资料

  • NVD 数据库:https://nvd.nist.gov/vuln/detail/CVE-2021-23017
  • X41 D-Sec GmbH 分析报告:https://www.x41-dsec.de/lab/advisories/x41-2021-001-nginx/