Feb 25, 2026·6 min read·3 visits
A heap-based buffer overflow in `gif2apng` 1.9 allows attackers to crash the application or potentially execute code via a crafted GIF file. The flaw resides in the main loop processing frame delays, leading to a 2-byte write past the allocated buffer end.
In the dusty corners of legacy image conversion tools lies CVE-2021-45911, a classic heap-based buffer overflow in `gif2apng`. This vulnerability exposes a fundamental flaw in how the tool handles GIF frame delays, allowing a 2-byte out-of-bounds write. While it sounds small, in the delicate ecosystem of the heap, two bytes are often all you need to corrupt metadata and hijack execution flow. This report dissects the failure of trust between the file parser and the memory allocator.
Let's be honest: gif2apng isn't the sexiest tool in your arsenal. It does exactly one thing—converts animated GIFs to Animated PNGs. It’s the kind of utility that sits deep inside automated image processing pipelines, quietly churning through user uploads without complaint. And that is exactly what makes it a prime target.
Automated pipelines are the holy grail for attackers. You don't need to phish a sysadmin; you just need to upload a funny cat GIF that happens to be malformed in a very specific, mathematical way. Because gif2apng runs as a command-line tool, it often inherits the permissions of the web server or the processing agent invoking it. If you pop this, you aren't just crashing a converter; you're gaining a foothold on the processing node.
The vulnerability in question, CVE-2021-45911, is a textbook example of "trusting the file format." The developers assumed that the number of frames declared in the header matched reality. Spoiler alert: In the hacker's world, reality is whatever we byte-edit it to be.
The root cause here is a classic disconnect between allocation and iteration. The GIF format specifies frame delays in Graphic Control Extension (GCE) blocks. To convert these to APNG, the tool needs to store the delay for every single frame.
Here is the logic failure: The program allocates a heap buffer to store these delays based on an initial calculation or assumption of the frame count. However, as it iterates through the actual blocks in the file to populate this buffer, it forgets to check if it has reached the edge of the map.
It's like inviting 10 people to dinner, setting the table for 10, but then keeping the door open while 50 people walk in and try to sit in the same 10 chairs. Eventually, someone sits on the floor—or in this case, writes 2 bytes of data into the adjacent heap chunk. This is a Heap-based Buffer Overflow (CWE-787). Specifically, it's a loop that writes unsigned short (16-bit) delay values linearly into memory until the file says "stop," regardless of what malloc said earlier.
Let's look at the pseudo-logic that caused this mess. While the exact source requires diffing the binary or the Debian patch, the pattern is unmistakable to anyone who has audited C code.
The Vulnerable Logic:
// 1. Allocation based on header info or fixed guess
unsigned short* delays = (unsigned short*)malloc(frames * sizeof(unsigned short));
// 2. The fatal loop
while (get_next_block(gif)) {
if (is_graphic_control_ext) {
// CRITICAL FAIL: No check if 'current_frame' < 'frames'
delays[current_frame] = get_delay_time(gif);
current_frame++;
}
}When current_frame exceeds the value used in the malloc, delays[current_frame] writes 2 bytes into the wild. In the heap implementation (glibc), the memory immediately following your buffer usually contains the metadata header for the next chunk. By overwriting the prev_size or size fields of the next chunk, an attacker prepares the heap for corruption during the next free() or malloc() operation.
The Fix (Debian/Upstream): The patch is boringly effective. It introduces a boundary check before the write operation:
if (current_frame >= allocated_frames) {
// Reallocate or Error out
fprintf(stderr, "Error: More frames than expected.\n");
break;
}
delays[current_frame] = delay_value;Exploiting a 2-byte overflow is an art form. It's not like a stack overflow where you just smash the return pointer and go home. You have to massage the heap layout (Feng Shui) so that the object immediately following your delays buffer is something interesting.
The Attack Plan:
N declared frames but N+1 GCE blocks. The N+1th block contains a specific delay value (the payload).PREV_INUSE bit or modify the chunk size.free(delays), or when it processes the next object, the allocator attempts to coalesce chunks or verify metadata. Because we corrupted the size/flags, the allocator gets confused and can be tricked into writing data to an arbitrary address (House of Spirit, House of Lore, or similar glibc attacks techniques, depending on the libc version).While this is listed as a "DoS" by conservative estimates, a determined exploit developer treats every heap overflow as a potential RCE until proven otherwise.
In a vacuum, crashing a CLI tool is annoying. In production, it's a denial of service. But if this tool is part of a web service (e.g., "Upload your funny GIF!"), it becomes a remote attack vector.
If the exploit succeeds in achieving execution, the attacker is running code inside your image processing container. From there, they can exfiltrate processed images, pivot to internal metadata services (hello AWS 169.254.169.254), or simply mine crypto on your CPU dime.
The real danger here is the ubiquity of these small, forgotten libraries. gif2apng isn't updated as frequently as ffmpeg or ImageMagick, meaning this bug likely sat in repositories for years, silently vulnerable, waiting for someone to notice that the frame counter wasn't wearing a seatbelt.
If you are running Debian Stretch, Buster, or Bullseye, or any distro that pulls from them, you are likely affected. The fix is straightforward: update your packages.
Remediation: Run your package manager's update command. For Debian/Ubuntu systems:
sudo apt-get update
sudo apt-get install --only-upgrade gif2apngDefense in Depth: Never run image processors on bare metal. If you must process untrusted user content, wrap the converter in a sandbox like Bubblewrap or a restrictive Docker container with no network access and limited filesystem permissions. Even if the heap exploits work, the shell they pop should be useless.
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
gif2apng gif2apng project | = 1.9 | 1.9+srconly-2+deb9u2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-787 (Out-of-bounds Write) |
| CVSS v3.1 | 7.8 (High) |
| Attack Vector | Local / User Interaction (File) |
| EPSS Score | 0.16% (Low probability of wild exploitation) |
| Exploit Status | Proof of Concept (PoC) Available |
| KEV Status | Not Listed |
The software writes data past the end, or before the beginning, of the intended buffer.