安全研究

安全漏洞
libpng png_read_png远程整数溢出漏洞

发布日期:2004-08-04
更新日期:2004-08-05

受影响系统:
libpng libpng 1.2.5
描述:
CVE(CAN) ID: CVE-2004-0599

libpng是多种应用程序使用的解析PNG图象格式的库。

libpng png_read_png()在处理PNG图象宽度时存在整数溢出问题,远程攻击者可以利用这个漏洞对应用程序进行拒绝服务攻击。

问题存在于:

      info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
         info_ptr->height * sizeof(png_bytep));

如果PNG使用超大的宽度值,可在内存分配时导致整数溢出。

攻击者可以构建恶意PNG文件,诱使用户解析,可能导致应用程序崩溃。

<*来源:chris (chris@cr-secure.net
  
  链接:http://marc.theaimsgroup.com/?l=bugtraq&m=109164344215165&w=2
        http://www.us-cert.gov/cas/techalerts/TA04-217A.html
*>

建议:
厂商补丁:

libpng
------
使用如下补丁程序:

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))

浏览次数:3209
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障