Hotdry.
ai-security

剖析 libpng 1.6.51 修复的四个 buffer overflow 漏洞:边界检查与 fuzz 补丁实现

libpng 1.6.51 通过 fuzzing 发现并修复四个 buffer overflow,聚焦 PNG chunk 解析和图像处理边界。剖析触发机制、补丁参数与工程安全清单。

在图像处理库中,libpng 作为 PNG 格式的标准实现,被广泛用于浏览器、图像查看器和游戏引擎等软件。buffer overflow 是其经典安全隐患,尤其在解析复杂 PNG chunk 时,边界检查缺失易导致堆溢出或越界读取。2025 年 11 月 22 日发布的 libpng 1.6.51 版本,通过 fuzzing 和安全研究修复了四个此类漏洞(CVE-2025-64505、CVE-2025-64506、CVE-2025-64720、CVE-2025-65018),其中两个高危(CVSS 7.1),两个中危(CVSS 6.1)。这些漏洞影响 1.6.0 至 1.6.50 版本,需要用户处理恶意 PNG 文件才能触发,但可能造成信息泄露、拒绝服务甚至任意代码执行。

漏洞成因剖析:PNG 解析中的边界失控

PNG 文件结构复杂,包括 IHDR(图像头)、PLTE(调色板)、IDAT(图像数据)等 chunk。libpng 在处理这些 chunk 时,依赖动态分配的堆缓冲区进行解压、转换和合成。漏洞根源在于未严格验证输入尺寸与输出缓冲匹配,尤其在量化(quantize)、调色板预乘(premultiplication)和行组合(row combine)阶段。

  1. CVE-2025-64505(中危,堆缓冲区 over-read):发生在 png_do_quantize 函数中,恶意调色板索引超出 palette 数组边界。fuzz 输入构造畸形 palette chunk,导致读取未初始化内存。证据:Samsung-PENTEST 报告显示,索引值 > 255 时,直接偏移 palette [invalid],泄露堆内容。

  2. CVE-2025-64506(中危,堆缓冲区 over-read):png_write_image_8bit 函数在 8-bit 输入且启用 convert_to_8bit 时,边界未对齐。weijinjinnihao fuzz 发现,输入尺寸计算忽略了通道转换,导致 over-read。

  3. CVE-2025-64720(高危,out-of-bounds read):png_image_read_composite 中的调色板预乘操作,结合 PNG_FLAG_OPTIMIZE_ALPHA 标志。Samsung-PENTEST 指出,premultiplication 时 alpha 通道未检查像素索引,读取超出合成缓冲区。

  4. CVE-2025-65018(高危,堆缓冲区 overflow):最典型一例,焦点在简化 API png_image_finish_read 处理 16-bit 交错(Adam7)PNG 时请求 8-bit 输出。用户按 PNG_IMAGE_SIZE (image) 分配缓冲(假设 8-bit RGBA,32x32 像素仅 4096 字节),但 png_combine_row 使用 IHDR 声明的 16-bit 深度(6 字节 / 像素)写入,导致 6144 字节溢出 2048 字节。更大图像(如 256x256)溢出达 131072 字节。“libpng 1.6.51 修复了 CVE-2025-65018,该漏洞在处理 16-bit 交错 PNG 时导致堆溢出。”[1] yosiimich 通过 fuzz 报告,Fabio Gritti 和 John Bowler 分析确认,仅交错图像受影响,非交错路径安全。

这些漏洞凸显 fuzzing(如 AFL 或 libFuzzer)在发现边界问题的价值:随机变异 PNG chunk(如 bit-depth=16, interlace=Adam7),结合 AddressSanitizer(ASan)快速定位。

补丁实现:精确边界检查与缓冲策略

libpng 维护者 Cosmin Truta 在 GitHub commits 中实现了针对性修复,避免破坏 API 兼容性。

  • 通用策略:所有修复前置边界检查,如索引 < palette_size,row_bytes <= allocated_size。使用 png_error 提前返回,防止下游崩溃。

  • CVE-2025-65018 深度补丁: 初始 commit 16b5e38 添加 bit-depth 验证:若 IHDR=16-bit 且输出非 linear(8-bit),拒绝处理。但这过于严格,破坏合法非交错场景。 最终 commit 218612d 重构:引入 do_local_scale 标志,仅交错图像启用中间缓冲 local_row(png_malloc (png_get_rowbytes (png_ptr, info_ptr)) 大小为转换后 8-bit)。流程:

    1. png_set_scale_16 启用 16-to-8 缩放。
    2. 若 interlaced,分配 local_row。
    3. png_image_read_direct_scaled:逐 pass png_read_row 到 local_row(已转换 8-bit),memcpy 到用户缓冲。
    4. png_free (local_row) 释放。 这确保 png_combine_row 只写到足够缓冲,避免 IHDR 深度溢出,同时保持非交错快速路径。

其他 CVE 类似:png_do_quantize 添加 index < num_palette;png_write_image_8bit 调整 convert_to_8bit 边界。

可落地工程参数与清单

升级 libpng 是首要,但工程化需参数化防御。

  1. 升级清单

    • 立即拉取 v1.6.51:git checkout v1.6.51 或下载 release。
    • 应用所有修复 commit:6a528eb(64505)、2bd84c0(64506)、08da33b(64720)、16b5e38+218612d(65018)。
    • 验证:编译测试套件,ASan 无 overflow。
  2. fuzzing 参数配置(用 libFuzzer):

    ./fuzz_png_read $CORPUS_DIR -max_len=10M -timeout=10 -runs=1e8
    
    • corpus: 合法 PNG + 变异 chunk(bit-depth=16, interlace=1, malformed palette)。
    • 监控:ASan stack-use-after-scope, heap-buffer-overflow。
    • 阈值:超时 10s,长度上限 10MB(PNG 典型)。
  3. 运行时防御参数

    参数 作用
    PNG_SAFE_READ 1 启用安全读取,拒绝畸形 chunk
    PNG_USER_MEM custom_alloc 带 canary 的堆分配
    ASan options halt_on_error=1 立即崩溃报告
    Valgrind --tool=memcheck --track-origins=yes 检测 uninit read
  4. 监控与回滚

    • Prometheus 指标:png_read_errors_total >5 / 分钟 告警。
    • 沙箱隔离:seccomp 限制 mprotect,防止 RCE。
    • 回滚阈值:崩溃率 >1%,降级到 1.6.50 + 手动 patch。
  5. 代码清单:安全 PNG 加载

    png_image image;
    memset(&image, 0, sizeof(image));
    image.version = PNG_IMAGE_VERSION;
    if (png_image_begin_read_from_file(&image, filename)) {
        image.format = PNG_FORMAT_RGBA;  // 显式指定,避免 auto
        size_t size = PNG_IMAGE_SIZE(image);
        void* buffer = malloc(size);
        if (buffer && png_image_finish_read(&image, NULL, buffer, 0, NULL)) {
            // 处理 buffer
        }
        free(buffer);
    }
    

    添加:检查 image.warning_or_error=0。

这些实践确保内存安全,即使上游有遗漏。libpng 事件提醒:图像库需 fuzz 覆盖率 >90%,边界参数化。

资料来源: [1] https://www.openwall.com/lists/oss-security/2025/11/22/1 [2] https://github.com/pnggroup/libpng/security/advisories/GHSA-7wv6-48j4-hj3g [3] https://github.com/pnggroup/libpng/commit/16b5e3823918840aae65c0a6da57c78a5a496a4d 等 commits。

(正文字数:1256)

查看归档