Buffer overflow in unzip with hand-crafted ZIP file

Bug #387350 reported by Giovanni Bajo on 2009-06-15
16
This bug affects 2 people
Affects Status Importance Assigned to Milestone
unzip
Unknown
Unknown
unzip (Ubuntu)
Low
Unassigned

Bug Description

Binary package hint: unzip

When using the attached handcrafted zip file with "unzip -l" (listing), I get the following output:

$ unzip -lv hello.zip
Archive: hello.zip
 Length Method Size Ratio Date Time CRC-32 Name
-------- ------ ------- ----- ---- ---- ------ ----
*** buffer overflow detected ***: unzip terminated
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)[0xb7fa0da8]
/lib/tls/i686/cmov/libc.so.6[0xb7f9eeb0]
/lib/tls/i686/cmov/libc.so.6[0xb7f9e5a8]
/lib/tls/i686/cmov/libc.so.6(_IO_default_xsputn+0xc8)[0xb7f10bb8]
/lib/tls/i686/cmov/libc.so.6(_IO_vfprintf+0xf4c)[0xb7ee377c]
/lib/tls/i686/cmov/libc.so.6(__vsprintf_chk+0xa4)[0xb7f9e654]
/lib/tls/i686/cmov/libc.so.6(__sprintf_chk+0x2d)[0xb7f9e59d]
unzip[0x80560e1]
unzip[0x8058539]
unzip[0x8058697]
unzip[0x804af3d]
unzip[0x804b20f]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe5)[0xb7eb9775]
unzip[0x8049391]
======= Memory map: ========
08048000-08067000 r-xp 00000000 08:07 53597 /usr/bin/unzip
08067000-08068000 r--p 0001e000 08:07 53597 /usr/bin/unzip
08068000-08069000 rw-p 0001f000 08:07 53597 /usr/bin/unzip
08069000-0807b000 rw-p 08069000 00:00 0
08646000-08667000 rw-p 08646000 00:00 0 [heap]
b7e42000-b7e4f000 r-xp 00000000 08:07 6949 /lib/libgcc_s.so.1
b7e4f000-b7e50000 r--p 0000c000 08:07 6949 /lib/libgcc_s.so.1
b7e50000-b7e51000 rw-p 0000d000 08:07 6949 /lib/libgcc_s.so.1
b7e63000-b7ea2000 r--p 00000000 08:07 11726 /usr/lib/locale/en_US.utf8/LC_CTYPE
b7ea2000-b7ea3000 rw-p b7ea2000 00:00 0
b7ea3000-b7fff000 r-xp 00000000 08:07 75569 /lib/tls/i686/cmov/libc-2.9.so
b7fff000-b8000000 ---p 0015c000 08:07 75569 /lib/tls/i686/cmov/libc-2.9.so
b8000000-b8002000 r--p 0015c000 08:07 75569 /lib/tls/i686/cmov/libc-2.9.so
b8002000-b8003000 rw-p 0015e000 08:07 75569 /lib/tls/i686/cmov/libc-2.9.so
b8003000-b8006000 rw-p b8003000 00:00 0
b8011000-b8018000 r--s 00000000 08:07 7511 /usr/lib/gconv/gconv-modules.cache
b8018000-b801a000 rw-p b8018000 00:00 0
b801a000-b801b000 r-xp b801a000 00:00 0 [vdso]
b801b000-b8037000 r-xp 00000000 08:07 76344 /lib/ld-2.9.so
b8037000-b8038000 r--p 0001b000 08:07 76344 /lib/ld-2.9.so
b8038000-b8039000 rw-p 0001c000 08:07 76344 /lib/ld-2.9.so
bfa24000-bfa39000 rw-p bffeb000 00:00 0 [stack]
Aborted

The file has been modified so to report an unknown compression method with ordinal number 0x3FFF. unzip tries to display the method number in decimal (%3u), but only reserve buffer space for 3 characters, as can be seen here (unzip-5.52, file list.c, function list_files, around line 114):

    char methbuf[8];
    static ZCONST char dtype[]="NXFS"; /* see zi_short() */
    static ZCONST char Far method[NUM_METHODS+1][8] =
        {"Stored", "Shrunk", "Reduce1", "Reduce2", "Reduce3", "Reduce4",
         "Implode", "Token", "Defl:#", "Def64#", "ImplDCL", "PKres11",
         "BZip2", "Unk:###"};

The "Unk:###" is the one being used, and "#" is supposed to be replaced by the method number. Increasing "methbuf" size (eg: to 16 characters) fixes the buffer overflow.

For reference, this is where the buffer overflow really happens (around line 330):

            methnum = MIN(G.crec.compression_method, NUM_METHODS);
            zfstrcpy(methbuf, method[methnum]);
            if (methnum == DEFLATED || methnum == ENHDEFLATED) {
                methbuf[5] = dtype[(G.crec.general_purpose_bit_flag>>1) & 3];
            } else if (methnum >= NUM_METHODS) {
                sprintf(&methbuf[4], "%03u", G.crec.compression_method);
            }

The last sprintf() only has space for 3 characters (and in fact uses %03u formatting string), but it does not take into account that compression_method is actually an unbounded 16-bit unsigned value.

Kees Cook (kees) wrote :

Thanks for this investigation! It looks like the overflow is not very harmful, so I'm unmarking this a security bug. A single byte overflow in the bss region is happening, which does not appear to be near any control structures.

Changed in unzip (Ubuntu):
status: New → Triaged
security vulnerability: yes → no
visibility: private → public
Gabe Gorelick (gabegorelick) wrote :

Is this bug still present in latest version? If so, this should be filed upstream at http://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=unzip.

Gabe Gorelick (gabegorelick) wrote :

I can confirm this on the unzip 6.0 used in karmic. The code in list.c has changed a little, but the same general problem remains.

Gabe Gorelick (gabegorelick) wrote :

Filed this upstream with the unzip people.

Hideki Yamane (henrich) wrote :

Hi,

I suppose when you report bug to upstream, "Info-ZIP Discussion Forum" is better than
sf.net. See http://www.info-zip.org/board/board.pl

and I cannot reproduce it in Debian unstable.

henrich@hp115:/tmp$ unzip -lv hello.zip
Archive: hello.zip
 Length Method Size Cmpr Date Time CRC-32 Name
-------- ------ ------- ---- ---------- ----- -------- ----
      14 Unk:62463 14 0% 2009-06-16 00:14 7b55a718 hello.txt
-------- ------- --- -------
      14 14 0% 1 file
henrich@hp115:/tmp$ unzip -v
UnZip 6.00 of 20 April 2009, by Debian. Original by Info-ZIP.

Latest sources and executables are at ftp://ftp.info-zip.org/pub/infozip/ ;
see ftp://ftp.info-zip.org/pub/infozip/UnZip.html for other sites.

Compiled with gcc 4.4.3 for Unix (Linux ELF) on Mar 7 2010.

UnZip special compilation options:
        ACORN_FTYPE_NFS
        COPYRIGHT_CLEAN (PKZIP 0.9x unreducing method not supported)
        SET_DIR_ATTRIB
        SYMLINKS (symbolic links supported, if RTL and file system permit)
        TIMESTAMP
        UNIXBACKUP
        USE_EF_UT_TIME
        USE_UNSHRINK (PKZIP/Zip 1.x unshrinking method supported)
        USE_DEFLATE64 (PKZIP 4.x Deflate64(tm) supported)
        UNICODE_SUPPORT [wide-chars, char coding: UTF-8] (handle UTF-8 paths)
        LARGE_FILE_SUPPORT (large files over 2 GiB supported)
        ZIP64_SUPPORT (archives using Zip64 for large files supported)
        USE_BZIP2 (PKZIP 4.6+, using bzip2 lib version 1.0.5, 10-Dec-2007)
        VMS_TEXT_CONV
        WILD_STOP_AT_DIR
        [decryption, version 2.11 of 05 Jan 2007]

UnZip and ZipInfo environment options:
           UNZIP: [none]
        UNZIPOPT: [none]
         ZIPINFO: [none]
      ZIPINFOOPT: [none]

Gabe Gorelick (gabegorelick) wrote :

What Debian package version of unzip are you using? I notice that on Karmic, it's 6.0-1, but unzip will still report its version as 6.0.

Hideki Yamane (henrich) wrote :

I'm using 6.0-4.

$ dpkg -s unzip
Package: unzip
Status: install ok installed
Priority: optional
Section: utils
Installed-Size: 396
Maintainer: Santiago Vila <email address hidden>
Architecture: i386
Version: 6.0-4
(snip)

Hideki Yamane (henrich) wrote :

Also I'm using i386 and amd64 and unzip packages are same version.

Gabe Gorelick (gabegorelick) wrote :

Hmm, looking at the Debian change log between 6.0-1 and 6.0-4, I don't see any changes that would fix this. I'm going to try to build it on Karmic and see if this bug really is gone.

Gabe Gorelick (gabegorelick) wrote :

I still get this using 6.0-4 from Debian. Perhaps you can't reproduce it because the buffer overflow just isn't detected?

Hideki Yamane (henrich) wrote :

Yes, Gabe, you're right, I could reproduce that with Fedora13 alpha.

Kees Cook (kees) on 2010-04-03
Changed in unzip (Ubuntu):
importance: Undecided → Low
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.