CVE-2019-6976:Libvips 内存泄露
字数 1344 2025-08-29 08:32:24
Libvips 内存泄露漏洞(CVE-2019-6976)分析与教学文档
漏洞概述
CVE-2019-6976是libvips图像处理库中存在的一个内存泄露漏洞,攻击者可以通过特制的PNG图片触发该漏洞,导致服务器泄露未初始化的内存数据。该漏洞影响libvips 8.7.4之前的版本。
漏洞发现背景
在一次渗透测试中,安全研究人员发现目标网站的图片上传功能存在异常:
- 上传特定图片后,服务器生成的缩略图变成了随机像素
- 这些"噪音"图片实际上是未初始化的内存数据
- 漏洞允许跨用户会话泄露敏感信息
漏洞影响
- 内存数据泄露:攻击者可获取服务器进程地址空间中的敏感信息
- 会话劫持风险:可能泄露其他用户的会话数据
- 影响范围:所有使用受影响版本libvips的应用程序
技术分析
漏洞根源
漏洞位于libvips处理PNG图片的IDAT区块时:
- PNG使用zlib/deflate压缩算法
- 攻击者可以构造特制的PNG图片,其中包含无效的窗口大小(CINFO=8)
- libvips在处理这种异常图片时,会泄露未初始化的内存数据
漏洞验证方法
-
构造恶意PNG:
- 修改PNG文件中的CMF字节,将CINFO字段设置为8(无效值)
- 可以使用hex编辑器手动修改或使用Kaitai结构分析工具
-
内存分配模式:
void* allocs[10240];
int asizes[4] = {6088,95000,775,6088}; // 调试确定的大小
for(int i = 0; i<10240; i++){
allocs[i] = g_malloc(asizes[i % 4]);
memset(allocs[i], 0xf1 + (i % 4), asizes[i % 4]);
}
for(int i=0;i<10240;i++){
if (1 || i % 4 == 0 || i % 4 == 2){
g_free(allocs[i]);
}
}
- 检测泄露:
- 使用ASAN(AddressSanitizer)编译libvips可增强泄露数据的可读性
- 正常图片与恶意图片的压缩率差异可达10倍
漏洞修复
修复方案非常简单,将g_malloc替换为g_malloc0(初始化为0的内存分配):
- buf = g_malloc( size );
+ buf = g_malloc0( size );
- if( !(buf = g_try_malloc( size )) ) {
+ if( !(buf = g_try_malloc0( size )) ) {
攻击利用建议
黑盒测试方法
-
指纹识别:
- 将libvips指纹添加到fingerping库中
- 上传测试图片并观察响应
-
压缩率检测:
- 通过比较原始图片和服务器生成图片的压缩率
- 内存泄露图片通常有更高的熵值(压缩率低)
白盒测试方法
-
使用Valgrind检测:
- 修复前后的Valgrind输出有明显差异
-
Fuzzing测试:
- 虽然常规fuzzing难以发现此类漏洞
- 需要专门针对内存初始化状态的测试
防御建议
-
及时更新:
- 升级到libvips 8.7.4或更高版本
-
深度防御:
- 实现fail-fast机制,遇到异常数据立即停止处理
- 使用内存安全的图像处理库处理不受信输入
-
运行时保护:
- 使用ASAN等工具进行内存错误检测
- 考虑使用Valgrind进行定期检查
漏洞时间线
- 2019-01-18:向libvips和Sharp报告漏洞
- 2019-01-18:libvips 8.7.4发布修复
- 2019-01-18:通知各大Linux发行版
- 2019-01-18:Sharp实现fail-fast机制
- 2019-01-18:各发行版陆续更新
教学总结
- 漏洞本质:未初始化内存使用导致信息泄露
- 触发条件:特制的PNG图片(无效zlib窗口大小)
- 影响评估:跨会话信息泄露风险
- 修复关键:确保内存分配后初始化
- 检测方法:压缩率分析、Valgrind检测
- 防御策略:及时更新、深度防御、运行时保护
此漏洞案例展示了:
- 图像处理库中隐藏的安全风险
- 内存安全编程的重要性
- 开源生态中协同修复的高效性
- 黑盒与白盒测试技术的结合应用