<<< Date Index >>>     <<< Thread Index >>>

GIMP gifload.exe GIF file (image width)*(image height)==0 DOS vulnerability





GIMP gifload.exe GIF file (image width)*(image height)==0 DOS vulnerability

******
Author
******

Hongzhen Zhou ( Fortinet,inc )
{
  felix__zhou _at_ hotmail _dot_ com
  hzhou _at_ fortinet _dot_ com
}

********************
vulnerable version
********************

Just tested on GIMP version 2.2.3 & 2.0.5 for windows
But the laster version 2.2.4 for all platform should be vulnerable.

**********
descriptor
**********

The GIMP is the GNU Image Manipulation Program. It is a freely distributed
piece of software for such tasks as photo retouching, image composition 
and image authoring. It works on many operating systems, in many languages.
Thge GIMP uses a plugin (gifload) to parse the GIF file format. The gifload
has a DOS vulnerability when it processes some special GIF files.

*********************
vulnerability details
*********************

GIMP use gifload.exe to load a GIF file. The gifload.exe did't check the 
value of width and height fields in image descriptor when read from GIF 
file(not the screen width and height field), it used its to 
generate a size to call g_malloc() and it did't check the return pointer 
value from g_malloc() yet before used the pointer. So if gifload.exe got 
0 from the width or height field of image descriptor which read from the 
GIF file, it crashed.

Change a normal gif file's image width value or image height value to 0 
and open it using GIMP.exe to see the gifload.exe die! I tested it on
GIMP version 2.2.3 & 2.0.5 for windows. But the laster version 2.2.4 for all
platform should be vulnerable.

Reported to vendor in Mar 2, 2005.

==============================================
source code from gimp-2.2.4\plug-ins\common\gifload.c
==============================================
----------------------------------------------
// load_image()
----------------------------------------------
// Didn't check the value of width and height fields in image descriptor 
// when read from file
---------------
if (!useGlobalColormap)
        {
          if (ReadColorMap (fd, bitPixel, localColorMap, &grayScale))
            {
              g_message ("Error reading local colormap");
              return image_ID; 
            }
          image_ID = ReadImage (fd, filename, LM_to_uint (buf[4], buf[5]),
                                LM_to_uint (buf[6], buf[7]),
                                localColorMap, bitPixel,
                                grayScale,
                                BitSet (buf[8], INTERLACE), imageCount,
                                (guint) LM_to_uint (buf[0], buf[1]),
                                (guint) LM_to_uint (buf[2], buf[3]),
                                GifScreen.Width,
                                GifScreen.Height
                                );
        }
      else
        {
          image_ID = ReadImage (fd, filename, LM_to_uint (buf[4], buf[5]),
                                LM_to_uint (buf[6], buf[7]),
                                GifScreen.ColorMap, GifScreen.BitPixel,
                                GifScreen.GrayScale,
                                BitSet (buf[8], INTERLACE), imageCount,
                                (guint) LM_to_uint (buf[0], buf[1]),
                                (guint) LM_to_uint (buf[2], buf[3]),
                                GifScreen.Width,
                                GifScreen.Height
                                );
        }
-----------------------------------------------
// ReadImage()  len==image width, height==image height 
-----------------------------------------------
// xpos and ypos are initialized to 0
gint xpos = 0, ypos = 0, pass = 0;

---------------
  if (alpha_frame)
    dest = (guchar *) g_malloc (len * height *
                                (promote_to_rgb ? 4 : 2));
    // dest == 0;
  else
    dest = (guchar *) g_malloc (len * height);
    // dest == 0;
---------------
          if (promote_to_rgb)
            {
              temp = dest + ( (ypos * len) + xpos ) * 4;
              // temp = 0 + ( (0 * 0) + 0) * 4;
              // temp == 0
              // So it cause write access exception!
              *(temp  ) = (guchar) cmap[0][v];
              *(temp+1) = (guchar) cmap[1][v];
              *(temp+2) = (guchar) cmap[2][v];
              *(temp+3) = (guchar) ((v == Gif89.transparent) ? 0 : 255);
            }
          else
            {
              temp = dest + ( (ypos * len) + xpos ) * 2;
              // temp = 0 + ( (0 * 0) + 0) * 2;
              *temp = (guchar) v;
              *(temp+1) = (guchar) ((v == Gif89.transparent) ? 0 : 255);
            }
-------------------------------------------------
That's all:)
=================================================