SECURITY ADVISORY about libpng-1.2.5 and earlier versions Revision 007 29 October 2004 COPYRIGHT and LICENSE Copyright 2004, Glenn Randers-Pehrson This document and these patches are distributed according to the same terms and conditions as libpng itself, as described in png.h. INTRODUCTION Here are the CVE names and CERT vulnerability numbers for the vulnerabilities that have been disclosed for libpng-1.2.5: CAN-2002-1363: Buffer overrun while adding filler bytes to 16-bit RGBA samples. CAN-2004-0768: Buffer overrun while adding filler bytes to 16-bit grayscale samples. CAN-2004-0597: CERT VU#388984: Remotely exploitable stack-based buffer overrun in png_handle_tRNS (pngrutil.c) CERT VU#817368: Dangerous code in png_handle_sBIT (pngrutil.c) (Similar code in png_handle_hIST). CAN-2004-0598: CERT VU#236656: Possible NULL-pointer crash in png_handle_iCCP (pngrutil.c) (this flaw is duplicated in multiple other locations). CAN-2004-0599: CERT VU#477512: Theoretical integer overflow in allocation in png_handle_sPLT (pngrutil.c) CERT VU#160448: Integer overflow in png_read_png (pngread.c) CERT VU#286464: Integer overflows during progressive reading. Two additional notices came to our attention on October 20, 2004: CAN-2004-0954: This appears to be a duplicate of CAN-2004-0597 (buffer overflow in png_handle_tRNS() ). According to the CVE dictionary, this name has been rejected as a duplicate. CAN-2004-0955: This appears to be a duplicate of CAN-2004-0599 (integer overflow in png_read_png() ). According to the CVE dictionary, this name has been reserved. This directory contains a set of patches for these libpng vulnerabilities (if this document has become separated from the patch set, you can find the patch set in the "DOWNLOAD" link from http://libpng.sf.net). This document, plus the patches and new libpng-1.2.6rc2 distribution, constitute the PNG Development Group's "vendor response" to the vulnerability reports. The worst of the vulnerabilities is a buffer overflow that can occur while reading the tRNS chunk, which is Item 1 of CAN-2004-0597. To defend against this, you can patch libpng using the appropriate one of libpng-patch-03, 03a, or 03b listed below, and/or use the warning_callback method described in "Patching applications that use libpng", below. PATCHING LIBPNG FOR INDIVIDUAL VULNERABILITIES Here are individual patches for each vulnerability, if you want to pick and choose which ones to fix (if you prefer to patch your entire library with a single combined patch, see the section entitled "PATCHING LIBPNG LIBRARIES", below): libpng-patch00-pngrtran-filler-RRGGBB-overflow.txt Fixes bug that was introduced in version 1.0.2 This bug was widely publicised in December 2002 and has been fixed in many Linux distributions. Mitre named this vulnerability CAN-2002-1363. Use to patch libpng-1.0.5 through 1.2.5 libpng-patch01-pngrtran-filler-GG-overflow.txt Fixes bug that was introduced in version 1.0.2 This bug was also publicised around January 2003. Because of its similarity to patch00, there has been some confusion and hardly anyone has applied this patch. There was a flurry of bug reports about this in June 2004 when people noticed that only half of the problem had been fixed. Mitre has assigned a new name, CAN-2004-0768, to this vulnerability. libpng-patch02-pngerror-memcpy-overflow.txt This bug was discovered in April 2004 and has been widely reported and patched (use patch02a for versions 1.2.3 and older). libpng-patch03-trns-chunk-overflow.txt This fixes the most dangerous of the newly reported vulnerabilities, which is CERT VU#388984 and Item 1 of CAN-2004-0597 (use patch03a for versions 0.89 through 1.0.5 and patch3b for versions 1.0.6 through 1.0.8). libpng-patch04-get-uint-31.txt This patch defines PNG_UINT_31_MAX, PNG_UINT_32_MAX, PNG_SIZE_MAX, and png_get_uint_31(), which are needed by patches 05-08 (use patch04a for libpng-1.0.5, patch04b for patch libpng-1.0.2 through 1.0.3, and patch04c for libpng-1.0.0 through 1.0.1). libpng-patch05-pngpread-chunklength.txt Fixes CERT VU#817368. Requires one of libpng-patch04* Use libpng-patch06-pngread-chunklength.txt to patch libpng-1.0.13 Fixes CERT VU#286464. Requires libpng-patch04-* (use patch06a for libpng-1.0.0 through 1.0.12, 1.2.0, and 1.2.1). libpng-patch07-png-read-png-overflow.txt Fixes CERT VU#160448, CAN-2004-0599. Libpng-1.0.5 and earlier didn't implement png_read_png(). Requires libpng-patch04-* libpng-patch08-splt-buffer-overflow.txt Fixes CERT VU#477512, CAN-2004-0598 (use patch08a to patch libpng-1.0.6 through 1.0.13, 1.2.0 through 1.2.3. Libpng-1.0.5 and earlier didn't implement sPLT chunk reading. Requires libpng-patch04-* libpng-patch09-null-iccp-profile.txt Use to patch libpng-1.0.9 through 1.2.5 Fixes CERT VU#236656, CAN-2004-0598. Does not work with libpng-1.0.6-1.0.8. Libpng-1.0.5 and earlier didn't implement iCCP chunk reading. libpng-patch10-find-duplicate-chunk.txt No security problem. The bugs are similar to the one fixed in patch 03, but the only effect is that libpng will fail to detect misplaced harmless duplicate chunks. Use to patch libpng-1.0.6 through 1.2.5 libpng-patch11-limit-dimensions.txt This patch avoids a host of security problems related to buffer overflows that might occur when processing very large images. It causes the reader to reject any images having more than one million rows or one milliion columns (use patch11a to patch libpng-0.96 through 1.0.9, patch11b to patch libpng-0.95, patch11c to patch libpng-0.90, and patch11d patch libpng-0.89c. PATCHING LIBPNG LIBRARIES We are also supplying combined patches that fix all of the vulnerabilities in a particular libpng distribution. This table identifies the proper combined patch for patching each pristine libpng distribution: lib version combined patch includes individual patches ============= ============================ ================================= libpng-0.89c libpng-0.89c-all-patches.txt 03a 11d libpng-0.90 libpng-0.90-all-patches.txt 03a 11c libpng-0.95 libpng-0.95-all-patches.txt 03a 04c 05 06a 11b libpng-0.96 libpng-1.0.1-all-patches.txt 03a 04c 05 06a 11a libpng-0.98 libpng-1.0.1-all-patches.txt 03a 04c 05 06a 11a libpng-0.99 libpng-1.0.1-all-patches.txt 03a 04c 05 06a 11a libpng-1.00 libpng-1.0.1-all-patches.txt 03a 04c 05 06a 11a libpng-1.01 libpng-1.0.1-all-patches.txt 03a 04c 05 06a 11a libpng-1.0.2 libpng-1.0.3-all-patches.txt 00-01 03a 04b 05 06a 11a libpng-1.0.3 libpng-1.0.3-all-patches.txt 00-01 03a 04b 05 06a 11a libpng-1.0.5 libpng-1.0.5-all-patches.txt 00-01 03a 04a 05 06a 11a libpng-1.0.6 libpng-1.0.8-all-patches.txt 00-01 03b 04-05 06a 07 08a 10 11a libpng-1.0.7 libpng-1.0.8-all-patches.txt 00-01 03b 04-05 06a 07 08a 10 11a libpng-1.0.8 libpng-1.0.8-all-patches.txt 00-01 03b 04-05 06a 07 08a 10 11a libpng-1.0.9 libpng-1.0.9-all-patches.txt 00-01 02a 03-05 06a 07 08a 9-10 11a libpng-1.0.10 libpng-1.2.1-all-patches.txt 00-01 02a 03-05 06a 07 08a 09-11 libpng-1.0.11 libpng-1.2.1-all-patches.txt 00-01 02a 03-05 06a 07 08a 09-11 libpng-1.0.12 libpng-1.2.1-all-patches.txt 00-01 02a 03-05 06a 07 08a 09-11 libpng-1.0.13 libpng-1.2.2-all-patches.txt 00-01 02a 03-07 08a 09-11 libpng-1.0.14 libpng-1.2.5-all-patches.txt 00-11 libpng-1.0.15 libpng-1.2.5-all-patches.txt 00-11 libpng-1.2.0 libpng-1.2.1-all-patches.txt 00-01 02a 03-05 06a 07 08a 09-11 libpng-1.2.1 libpng-1.2.1-all-patches.txt 00-01 02a 03-05 06a 07 08a 09-11 libpng-1.2.2 libpng-1.2.2-all-patches.txt 00-01 02a 03-07 08a 09-11 libpng-1.2.3 libpng-1.2.3-all-patches.txt 00-07 08a 09-11 libpng-1.2.4 libpng-1.2.5-all-patches.txt 00-11 libpng-1.2.5 libpng-1.2.5-all-patches.txt 00-11 Patching applications that use libpng You can also bullet-proof your *application* whether it is being run with a vulnerable libpng or not. Use a warning callback (which you register with libpng's png_read_create_struct() ) similar to this: void warning_callback(png_structp png_ptr, png_const_charp warning_msg) { /* convert tRNS warning to error */ if (strncmp(warning_msg,"Missing PLTE before tRNS",24) == 0) png_error(png_ptr, warning_msg); printf("libpng warning: %s.\n",warning_msg); } If you already have a warning callback function, just add the two-line "if (strncmp ... png_error()" statement. You can also protect your application from existing or future vulnerabilities in the parts of libpng that process chunks that you don't use. This method will cause libpng to skip over your unused chunks. You will need to add or subtract chunk names from the list, as appropriate for your application. This method only works if you are doing sequential reading. #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) png_byte unused_chunks[]= { 104, 73, 83, 84, '\0', /* hIST */ 105, 84, 88, 116, '\0', /* iTXt */ 112, 67, 65, 76, '\0', /* pCAL */ 115, 67, 65, 76, '\0', /* sCAL */ 115, 80, 76, 84, '\0', /* sPLT */ 116, 69, 88, 116, '\0', /* tEXt */ 116, 73, 77, 69, '\0', /* tIME */ 122, 84, 88, 116, '\0', /* zTXt */ }; #endif There is a complete list of integer representations of chunk types in png.h starting at line 2644. Put the following after your png_read_create_struct(): #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) /* Ignore unused chunks */ png_set_keep_unknown_chunks(png_ptr, 1, unused_chunks, (int)sizeof(unused_chunks)/5); #endif NOTE: Advisories prior to version 005, and the libpng manpage prior to 1.2.6rc3, incorrectly showed the second argument to png_set_keep_unknown_chunks as 0. You may also wish to place limits on the width and height of images that you will accept. Test for images exceeding your chosen limit immediately after your call to png_get_IHDR(). The new default limit in libpng-1.2.6rc2 and in patch11, above, is 1 million rows and 1 million columns (down from the default 2.147 billion in previous versions). PGP KEY If you need these: Glenn's PGP public key (29 October 04, replaces previous key): -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.2.6 (GNU/Linux) mQGiBEGCDvQRBADmTzR1TfIPvRhuUSjoXRas2GaoH6NhMWOhXPRlVCE8uPPZxsS5 pGR3wMnBqzHtH8n6QDRJvtumhAZpmOdOXkI6e9Xhwokn6UBHk4OPvWgmUhWJKzI5 v5Y8F+FCEIV4j7x8WXWUbiiw790JGgVgNLKKhG93LN6Gk+YuTcCrIZgbDwCguZfp J9FsubaCLbnEe1UdBgmqbxsEAMebCKDLr3oXaFiz4Cj8F+d22mv0Gt9j+XZKR+CO tT2BVAdU5tmjKxaesgWwFqWvQlQSaS8+2iteWeUb6Lg8q1YGJhwH9fQuX7+qL7yQ +/kKRt727V6YKhVbHCFMujUJVh6sECCV3aP4ZlDghlpykK07PzzgWVxko6zAmRfH +7+cA/9aAN02W4xi5JoHhsrm2cGj+MNr0BvGQ3jjL1AN0vJ48mDLJuMuLbFEnp/z 2qS3LThEKV5vVQ5vCCMxz/JKYfBErcAE7AWfZrIK8vNcFqy95Uhh3GnvCwLo/WCE hO2v68/WLwdeQhw4O39fEIbonjP/YlbB8Wol/iToPjEoXi6VE7Q4R2xlbm4gUmFu ZGVycy1QZWhyc29uIChsaWJwbmcpIDxnbGVubnJwQGltYWdlbWFnaWNrLm9yZz6I XgQTEQIAHgUCQYIO9AIbAwYLCQgHAwIDFQIDAxYCAQIeAQIXgAAKCRAV64VjAAMe flyaAJwI+CkKLCtPJ0qtaa89kfIve1kxiACfQ/eZUoJugB4E3eXeH2xHp7hwnIC5 AQ0EQYIO9RAEAPpJJjUO9ilwRA652bS6sWfwl9UTDruLPA7FpAR3qHm5NJlL7se6 /bqW5kFawr98Y/qiKTURmW6XJeZDwjHSUKPe52RD1pmY+wBUE7S91nE1gX7bhJ2/ bBoyK+rE/CfM+NtgCZyXCeEL4ZTsQoKzuDElX8tNr9pzthUIOjyigW6DAAMGA/9f 1kqSoN6CK/fUF1Bq5SUuKROXzVgQpWbl8Bzb47F6NS6ppGPJCJ01o1TvdrtsZ69a XAgJxRsNor797ultUeOO88ixWZLanTLNodXWNOKn1BNGceRyw1JBMkAEPy/zV54X qrJc1gb2VkMN/sYMtrqcoSwWsvztt1qrDcA0TRMzJIhJBBgRAgAJBQJBgg71AhsM AAoJEBXrhWMAAx5+NsIAoKprj4aqqgoILIOwlCndVxFbaQxGAKCn8l+C+r+0t02i OMCavw1dWRHnAA== =UQKZ -----END PGP PUBLIC KEY BLOCK----- ----------------------- rev 007 29 October 2004