Skip to content

Latest commit

 

History

History
161 lines (131 loc) · 4.65 KB

README-1.md

File metadata and controls

161 lines (131 loc) · 4.65 KB

CVE-2004-0597

Experiment Environment

Ubuntu 14.04 LTS

Ubuntu 11.04

INSTALL & Configuration

wget https://github.com/mudongliang/source-packages/raw/master/CVE-2004-0597/libpng-1.2.5.tar.gz

tar -xvf libpng-1.2.5.tar.gz
cd libpng-1.2.5/
1. copy makefile to root directory
cp scripts/makefile.linux makefile
make
sudo make install
2. just use makefile.linux
make -f scripts/makefile.linux
sudo make install -f scripts/makefile.linux

Problems in Installation & Configuration

How to trigger vulnerability

./pngtest pngtest_bad.png

PoCs

pngtest_bad.png

Vulnerability Details & Patch

Root Cause

pngrutils.c:1257

	png_crc_read(png_ptr, readbuf, (png_size_t)length);

Stack Trace

#0  0x0067bc45 in ?? () from /lib/i386-linux-gnu/libpng12.so.0
#1  0x41414141 in ?? ()
#2  0x41414141 in ?? ()
#3  0x41414141 in ?? ()

Patch

diff -ru libpng-1.2.5/png.h libpng-1.2.5.fix/png.h
--- libpng-1.2.5/png.h	2002-10-03 12:32:26.000000000 +0100
+++ libpng-1.2.5.fix/png.h	2004-07-13 23:18:10.000000000 +0100
@@ -835,6 +835,9 @@
 /* Maximum positive integer used in PNG is (2^31)-1 */
 #define PNG_MAX_UINT ((png_uint_32)0x7fffffffL)
 
+/* Constraints on width, height, (2 ^ 24) - 1*/
+#define PNG_MAX_DIMENSION 16777215
+
 /* These describe the color_type field in png_info. */
 /* color type masks */
 #define PNG_COLOR_MASK_PALETTE    1
diff -ru libpng-1.2.5/pngpread.c libpng-1.2.5.fix/pngpread.c
--- libpng-1.2.5/pngpread.c	2002-10-03 12:32:28.000000000 +0100
+++ libpng-1.2.5.fix/pngpread.c	2004-07-13 23:03:58.000000000 +0100
@@ -209,6 +209,8 @@
 
       png_push_fill_buffer(png_ptr, chunk_length, 4);
       png_ptr->push_length = png_get_uint_32(chunk_length);
+      if (png_ptr->push_length > PNG_MAX_UINT)
+         png_error(png_ptr, "Invalid chunk length.");
       png_reset_crc(png_ptr);
       png_crc_read(png_ptr, png_ptr->chunk_name, 4);
       png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
@@ -638,6 +640,8 @@
 
       png_push_fill_buffer(png_ptr, chunk_length, 4);
       png_ptr->push_length = png_get_uint_32(chunk_length);
+      if (png_ptr->push_length > PNG_MAX_UINT)
+         png_error(png_ptr, "Invalid chunk length.");
 
       png_reset_crc(png_ptr);
       png_crc_read(png_ptr, png_ptr->chunk_name, 4);
diff -ru libpng-1.2.5/pngrutil.c libpng-1.2.5.fix/pngrutil.c
--- libpng-1.2.5/pngrutil.c	2004-07-13 13:36:37.000000000 +0100
+++ libpng-1.2.5.fix/pngrutil.c	2004-07-13 23:43:02.000000000 +0100
@@ -350,7 +350,11 @@
    png_crc_finish(png_ptr, 0);
 
    width = png_get_uint_32(buf);
+   if (width > PNG_MAX_DIMENSION)
+      png_error(png_ptr, "Width is too large");
    height = png_get_uint_32(buf + 4);
+   if (height > PNG_MAX_DIMENSION)
+      png_error(png_ptr, "Height is too large");
    bit_depth = buf[8];
    color_type = buf[9];
    compression_type = buf[10];
@@ -675,7 +679,7 @@
    else
       truelen = (png_size_t)png_ptr->channels;
 
-   if (length != truelen)
+   if (length != truelen || length > 4)
    {
       png_warning(png_ptr, "Incorrect sBIT chunk length");
       png_crc_finish(png_ptr, length);
@@ -1244,7 +1248,8 @@
          /* Should be an error, but we can cope with it */
          png_warning(png_ptr, "Missing PLTE before tRNS");
       }
-      else if (length > (png_uint_32)png_ptr->num_palette)
+      if (length > (png_uint_32)png_ptr->num_palette ||
+          length > PNG_MAX_PALETTE_LENGTH)
       {
          png_warning(png_ptr, "Incorrect tRNS chunk length");
          png_crc_finish(png_ptr, length);
@@ -1400,7 +1405,7 @@
 void /* PRIVATE */
 png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
-   int num, i;
+   unsigned int num, i;
    png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
 
    png_debug(1, "in png_handle_hIST\n");
@@ -1426,8 +1431,8 @@
       return;
    }
 
-   num = (int)length / 2 ;
-   if (num != png_ptr->num_palette)
+   num = length / 2 ;
+   if (num != png_ptr->num_palette || num > PNG_MAX_PALETTE_LENGTH)
    {
       png_warning(png_ptr, "Incorrect hIST chunk length");
       png_crc_finish(png_ptr, length);
@@ -2868,6 +2873,9 @@
                png_read_data(png_ptr, chunk_length, 4);
                png_ptr->idat_size = png_get_uint_32(chunk_length);
 
+               if (png_ptr->idat_size > PNG_MAX_UINT)
+                  png_error(png_ptr, "Invalid chunk length.");
+            
                png_reset_crc(png_ptr);
                png_crc_read(png_ptr, png_ptr->chunk_name, 4);
                if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))

References

libPNG 1.2.5 stack-based buffer overflow and other code concerns