Bug 1204676 (CVE-2015-2331)

Summary: CVE-2015-2331 libzip: integer overflow when processing ZIP archives
Product: [Other] Security Response Reporter: Martin Prpič <mprpic>
Component: vulnerabilityAssignee: Red Hat Product Security <security-response-team>
Status: CLOSED NOTABUG QA Contact:
Severity: high Docs Contact:
Priority: high    
Version: unspecifiedCC: apatters, bleanhar, carnil, ccoleman, dajohnso, dclarizi, dmcphers, erik-fedora, falonso, fedora, gmccullo, jchaloup, jdetiber, jhardy, jialiu, jkeck, jokerman, jorton, jprause, jrafanie, jvlcek, knoha, kseifried, kvolny, lmeyer, manisandro, mmaslano, mmccomas, obarenbo, rcollet, rdieter, rhack, security-response-team, thoger, webstack-team, xlecauch
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: php 5.6.7, php 5.5.23, php 5.4.39 Doc Type: Bug Fix
Doc Text:
An integer overflow flaw, leading to a heap-based buffer overflow, was found in the way libzip, which is also embedded in PHP, processed certain ZIP archives. If an attacker were able to supply a specially crafted ZIP archive to an application using libzip, it could cause the application to crash or, possibly, execute arbitrary code.
Story Points: ---
Clone Of: Environment:
Last Closed: 2015-04-08 12:09:33 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 1204677, 1204678, 1208530, 1208531, 1208532, 1208533, 1209880    
Bug Blocks: 1204679    

Description Martin Prpič 2015-03-23 10:58:49 UTC
An integer overflow flaw, leading to a heap-based buffer overflow, was found in the way libzip, which is embedded in PHP, processed certain ZIP archives. If an attacker were able to supply a specially crafted ZIP archive to an application using libzip, it could cause the application to crash or, possibly, execute arbitrary code.

Upstream patch:

https://github.com/php/php-src/commit/ef8fc4b53d92fbfcd8ef1abbd6f2f5fe2c4a11e5

Upstream issue:

https://bugs.php.net/bug.php?id=69253

According to http://seclists.org/oss-sec/2015/q1/885 , libzip upstream has been notified of this issue.

Comment 1 Martin Prpič 2015-03-23 10:59:44 UTC
Created libzip tracking bugs for this issue:

Affects: fedora-all [bug 1204677]

Comment 2 Martin Prpič 2015-03-23 10:59:48 UTC
Created mingw-libzip tracking bugs for this issue:

Affects: fedora-all [bug 1204678]

Comment 4 Francisco Alonso 2015-03-26 10:03:32 UTC
libzip upstream commit:

http://hg.nih.at/libzip/rev/9f11d54f692e

Comment 6 Fedora Update System 2015-03-31 21:42:09 UTC
mingw-libzip-0.11.2-3.fc22 has been pushed to the Fedora 22 stable repository.  If problems still persist, please make note of it in this bug report.

Comment 16 Fedora Update System 2015-04-05 14:31:47 UTC
mingw-libzip-0.11.2-3.fc21 has been pushed to the Fedora 21 stable repository.  If problems still persist, please make note of it in this bug report.

Comment 17 Fedora Update System 2015-04-05 14:33:05 UTC
mingw-libzip-0.11.2-3.fc20 has been pushed to the Fedora 20 stable repository.  If problems still persist, please make note of it in this bug report.

Comment 20 Tomas Hoger 2015-04-08 07:08:40 UTC
While the patch that was applied to libzip (either upstream or bundled with PHP, see comment 4 and comment 0 respectively) is applicable to libzip versions prior to 0.11, it is only required in 0.11 and later.  The 0.11 version introduced Zip64 support and made it possible to call the affected _zip_cdir_new() with large enough nentry argument to trigger overflow.

In versions before 0.11, the _zip_cdir_new() function was called from _zip_readcdir() function when reading Zip files.  The nentry value is directly read from an input file as short / 2 byte value.  Hence the maximum possible nentry value is 0xffff / 65535.  This is insufficient to trigger integer overflow when multiplied by sizeof(struct zip_dirent).

The following libzip upstream commit adds support for reading Zip64 central directory.

http://hg.nih.at/libzip/rev/6a817a320838

In this format, number of entries in the directory is stored as 64 bit value, rather than 16 bit used in the original Zip format.  There are now two code paths to call _zip_cdir_new() when reading Zip file - _zip_read_eocd() handling old central directory format and _zip_read_eocd64() handling Zip64 central directory.  In the latter case, nentry value is 64 bit and hence can trigger integer overflow in _zip_cdir_new().

Note that only this upstream commit changed nentry type in _zip_cdir_new() from int to zip_uint64_t, so it seems integer overflow was only possible on 32 bit systems for versions between this and the above commit.

http://hg.nih.at/libzip/rev/52de63d0c791#l7.1

Note that there is similar problem in the _zip_cdir_grow() function, which was introduced via the following commit:

http://hg.nih.at/libzip/rev/54290e506680

According to the NEWS file, it first appeared in version 0.9.1.  It seems this change can make it possible for a malicious Zip file to cause nentry to be incremented to value that triggers integer overflow (only on 32 bit systems, as nentry continues to be int).  However, as nentry is only incremented slowly (by 0xffff, which means less than 4mb increase on each re-allocation), it's not really possible to trigger this without causing memory allocation failure earlier.  Note that upstream commit linked in comment 4 does not correct the _zip_cdir_grow() function, but that function is no longer called in current 0.11.2 version.

The libzip packages in Red Hat Enterprise Linux 6 and 7 are based on upstream versions 0.9 and 0.10.1, and hence are not affected by this issue.

The PHP packages in Red Hat products embed the following libzip versions:
- PHP 5.3.3 (in Red Hat Enterprise Linux 5 and 6) - libzip 0.9.3
- PHP 5.4 and 5.5 (in Red Hat Enterprise Linux 7 and Red Hat Software Collections) - libzip 0.10.1
- PHP 5.6 - libzip 0.11.2

Therefore no PHP packages in Red Hat products were affected.  Neither upstream PHP 5.4 and 5.5 needed this handled as a security fix.

Comment 23 Tomas Hoger 2015-04-08 12:09:33 UTC
Statement:

This issue did not affect the versions of PHP as shipped with Red Hat Enterprise Linux 5, 6 and 7, and the versions of libzip as shipped with Red Hat Enterprise Linux 6 and 7.

Comment 25 Fedora Update System 2015-04-17 02:29:29 UTC
libzip-0.11.2-5.fc22 has been pushed to the Fedora 22 stable repository.  If problems still persist, please make note of it in this bug report.

Comment 26 Fedora Update System 2015-04-21 19:00:21 UTC
libzip-0.11.2-5.fc20 has been pushed to the Fedora 20 stable repository.  If problems still persist, please make note of it in this bug report.

Comment 27 Fedora Update System 2015-04-21 19:28:20 UTC
libzip-0.11.2-5.fc21 has been pushed to the Fedora 21 stable repository.  If problems still persist, please make note of it in this bug report.

Comment 28 Tomas Hoger 2015-04-22 15:05:09 UTC
(In reply to Tomas Hoger from comment #20)
> Note that upstream commit linked in comment 4 does not correct the
> _zip_cdir_grow() function, but that function is no longer called in
> current 0.11.2 version.

Unused _zip_cdir_grow() was now removed upstream:

http://hg.nih.at/libzip/rev/0fdf910ee373

Additional related commits, which add checks to memory allocation where overflows are not practically possible because of slow increase in memory usage (similar to what's described for _zip_cdir_grow() in comment 20) or called after zip_open(), and hence constrained by zip_open() / _zip_cdir_new() limits or checks.

http://hg.nih.at/libzip/rev/60accba29159#l12.1
http://hg.nih.at/libzip/rev/d9ed3a4b84d7#l5.1
http://hg.nih.at/libzip/rev/88c842788362