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头部的处理不当:
- 使用
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:处理数据
-
关键函数调用链:
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 -
漏洞触发细节:
- 在
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) {
修复逻辑:
- 在
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整数溢出漏洞
-
相关技术:
- 安全整数运算
- 边界检查技术
- 静态代码分析工具使用