Bug 1056996 (CVE-2017-14107)

Summary: VUL-0: CVE-2017-14107: libzip: The _zip_read_eocd64 function in zip_open.c in libzip before 1.3.0mishandles EOCD records, which allows remote attackers to cause adenial of service (memory allocation failure in _zip_cdir_grow inzip_dirent
Product: [Novell Products] SUSE Security Incidents Reporter: Marcus Meissner <meissner>
Component: IncidentsAssignee: Petr Gajdos <pgajdos>
Status: RESOLVED FIXED QA Contact: Security Team bot <security-team>
Severity: Normal    
Priority: P3 - Medium CC: astieger, smash_bz
Version: unspecified   
Target Milestone: ---   
Hardware: Other   
OS: Other   
URL: https://smash.suse.de/issue/191388/
Whiteboard: CVSSv3:SUSE:CVE-2017-14107:6.5:(AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H) CVSSv2:SUSE:CVE-2017-14107:5.0:(AV:N/AC:L/Au:N/C:N/I:N/A:P) CVSSv2:NVD:CVE-2017-14107:4.3:(AV:N/AC:M/Au:N/C:N/I:N/A:P) CVSSv3:RedHat:CVE-2017-14107:3.3:(AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L)
Found By: Security Response Team Services Priority:
Business Priority: Blocker: ---
Marketing QA Status: --- IT Deployment: ---
Attachments: 00330-libzip-memallocfailure-_zip_cdir_grow

Description Marcus Meissner 2017-09-04 06:37:43 UTC
From: "Agostino Sarubbo" <ago () gentoo org>
Date: Sat, 2 Sep 2017 18:41:51 +0000

Description:
libzip is a library for manipulating zip archives.

The relevant ASan output of the issue:

# ziptool $FILE cat index
==16798==ERROR: AddressSanitizer failed to allocate 0xc0a96a2000 (827476025344) bytes of LargeMmapAllocator (error 
code: 12)
==16798==Process memory map follows:
==16798==End of process memory map.
==16798==AddressSanitizer CHECK failed: 
/var/tmp/portage/sys-libs/compiler-rt-sanitizers-4.0.1/work/compiler-rt-4.0.1.src/lib/sanitizer_common/sanitizer_common.cc:120
 "((0 && "unable to mmap")) != (0)" (0x0, 0x0)
    #0 0x4da9ef in AsanCheckFailed 
/var/tmp/portage/sys-libs/compiler-rt-sanitizers-4.0.1/work/compiler-rt-4.0.1.src/lib/asan/asan_rtl.cc:69
    #1 0x4f5755 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) 
/var/tmp/portage/sys-libs/compiler-rt-sanitizers-4.0.1/work/compiler-rt-4.0.1.src/lib/sanitizer_common/sanitizer_termination.cc:79
    #2 0x4e4d82 in __sanitizer::ReportMmapFailureAndDie(unsigned long, char const*, char const*, int, bool) 
/var/tmp/portage/sys-libs/compiler-rt-sanitizers-4.0.1/work/compiler-rt-4.0.1.src/lib/sanitizer_common/sanitizer_common.cc:120
    #3 0x4ee685 in __sanitizer::MmapOrDie(unsigned long, char const*, bool) 
/var/tmp/portage/sys-libs/compiler-rt-sanitizers-4.0.1/work/compiler-rt-4.0.1.src/lib/sanitizer_common/sanitizer_posix.cc:132
    #4 0x42608a in __sanitizer::LargeMmapAllocator::Allocate(__sanitizer::AllocatorStats*, unsigned long, unsigned 
long) 
/var/tmp/portage/sys-libs/compiler-rt-sanitizers-4.0.1/work/compiler-rt-4.0.1.src/lib/asan/../sanitizer_common/sanitizer_allocator_secondary.h:41
    #5 0x42608a in __sanitizer::CombinedAllocator<__sanitizer::SizeClassAllocator64, 
__sanitizer::SizeClassAllocatorLocalCache<__sanitizer::SizeClassAllocator64 >, __sanitizer::LargeMmapAllocator 

    ::Allocate(__sanitizer::SizeClassAllocatorLocalCache<__sanitizer::SizeClassAllocator64 >*, unsigned long, unsigned 

long, bool, bool) 
/var/tmp/portage/sys-libs/compiler-rt-sanitizers-4.0.1/work/compiler-rt-4.0.1.src/lib/asan/../sanitizer_common/sanitizer_allocator_combined.h:70
    #6 0x42608a in __asan::Allocator::Allocate(unsigned long, unsigned long, __sanitizer::BufferedStackTrace*, 
__asan::AllocType, bool) 
/var/tmp/portage/sys-libs/compiler-rt-sanitizers-4.0.1/work/compiler-rt-4.0.1.src/lib/asan/asan_allocator.cc:407
    #7 0x420d3f in __asan::asan_realloc(void*, unsigned long, __sanitizer::BufferedStackTrace*) 
/var/tmp/portage/sys-libs/compiler-rt-sanitizers-4.0.1/work/compiler-rt-4.0.1.src/lib/asan/asan_allocator.cc:791
    #8 0x4d0df1 in realloc 
/var/tmp/portage/sys-libs/compiler-rt-sanitizers-4.0.1/work/compiler-rt-4.0.1.src/lib/asan/asan_malloc_linux.cc:93
    #9 0x7f4edab1b7e5 in _zip_cdir_grow /var/tmp/portage/dev-libs/libzip-1.2.0/work/libzip-1.2.0/lib/zip_dirent.c:108:37
    #10 0x7f4edab1b7e5 in _zip_cdir_new /var/tmp/portage/dev-libs/libzip-1.2.0/work/libzip-1.2.0/lib/zip_dirent.c:82
    #11 0x7f4edab390d0 in _zip_read_eocd64 
/var/tmp/portage/dev-libs/libzip-1.2.0/work/libzip-1.2.0/lib/zip_open.c:854:13
    #12 0x7f4edab390d0 in _zip_read_cdir /var/tmp/portage/dev-libs/libzip-1.2.0/work/libzip-1.2.0/lib/zip_open.c:285
    #13 0x7f4edab390d0 in _zip_find_central_dir 
/var/tmp/portage/dev-libs/libzip-1.2.0/work/libzip-1.2.0/lib/zip_open.c:613
    #14 0x7f4edab390d0 in _zip_open /var/tmp/portage/dev-libs/libzip-1.2.0/work/libzip-1.2.0/lib/zip_open.c:200
    #15 0x7f4edab369b7 in zip_open_from_source 
/var/tmp/portage/dev-libs/libzip-1.2.0/work/libzip-1.2.0/lib/zip_open.c:148:11
    #16 0x7f4edab35e93 in zip_open /var/tmp/portage/dev-libs/libzip-1.2.0/work/libzip-1.2.0/lib/zip_open.c:74:15
    #17 0x513392 in read_from_file /var/tmp/portage/dev-libs/libzip-1.2.0/work/libzip-1.2.0/src/ziptool.c:698:13
    #18 0x513392 in main /var/tmp/portage/dev-libs/libzip-1.2.0/work/libzip-1.2.0/src/ziptool.c:1113
    #19 0x7f4ed9c43680 in __libc_start_main 
/var/tmp/portage/sys-libs/glibc-2.23-r4/work/glibc-2.23/csu/../csu/libc-start.c:289
    #20 0x41b058 in _init (/usr/bin/ziptool+0x41b058)

Affected version:
1.2.0

Fixed version:
1.3.0

Commit fix:
https://github.com/nih-at/libzip/commit/9b46957ec98d85a572e9ef98301247f39338a3b5

Credit:
This bug was discovered by Agostino Sarubbo of Gentoo.

CVE:
CVE-2017-14107

Reproducer:
https://github.com/asarubbo/poc/blob/master/00330-libzip-memallocfailure-_zip_cdir_grow

Timeline:
2017-08-24: bug discovered and reported to upstream
2017-08-29: upstream released a fix
2017-09-01: blog post about the issue
2017-09-01: CVE assigned

Note:
This bug was found with American Fuzzy Lop.
This bug was identified with bare metal servers donated by Packet. This work is also supported by the Core 
Infrastructure Initiative.

Permalink:
https://blogs.gentoo.org/ago/2017/09/01/libzip-memory-allocation-failure-in-_zip_cdir_grow-zip_dirent-c/

--
Agostino Sarubbo
Gentoo Linux Developer


http://seclists.org/oss-sec/2017/q3/390
https://github.com/nih-at/libzip/commit/9b46957ec98d85a572e9ef98301247f39338a3b5
Comment 1 Marcus Meissner 2017-09-04 06:50:48 UTC
Created attachment 739256 [details]
00330-libzip-memallocfailure-_zip_cdir_grow

QA REPRODUCER:

install libzip-tools

ziptool 00330-libzip-memallocfailure-_zip_cdir_grow cat index
Comment 2 Petr Gajdos 2017-09-05 07:21:03 UTC
1.3.0 is not buildable trough failing testsuite. Author notified.
Comment 3 Petr Gajdos 2017-09-05 08:13:08 UTC
(In reply to Marcus Meissner from comment #1)
> ziptool 00330-libzip-memallocfailure-_zip_cdir_grow cat index

Unfortunately ziptool is quite new thing, new enough to not be included in sle12. There's also not a libzip-tools package, binaries (zipcmp, zipmerge and ziptorrent) are included in main package.

However, I am not able to reproduce anything (nor valgrind errors) with them:

$ zipcmp -t 00330-libzip-memallocfailure-_zip_cdir_grow 00330-libzip-memallocfailure-_zip_cdir_grow
zipcmp: cannot open zip archive `00330-libzip-memallocfailure-_zip_cdir_grow': Not a zip archive
$

$ zipmerge 00330-libzip-memallocfailure-_zip_cdir_grow 00330-libzip-memallocfailure-_zip_cdir_grow 
zipmerge: cannot open zip archive `00330-libzip-memallocfailure-_zip_cdir_grow': Not a zip archive
$
Comment 4 Petr Gajdos 2017-09-05 10:53:08 UTC
When patching 12/libzip, the libzip is so secure that refuses two zip archives from testsuite:

[   16s] FAIL: extra_count_ignore_zip64
[   16s] ==============================
[   16s] 
[   16s] extra_count_ignore_zip64: 
[   16s] running: ../modify bigzero.zip count_extra 0 l count_extra 0 c count_extra 0 lc
[   16s] extra_count_ignore_zip64 -- FAILED: zip file bigzero.zip wrong
[   16s] 
[   16s] FAIL: open_many_ok
[   16s] ==================
[   16s] 
[   16s] open_many_ok: 
[   16s] running: ../tryopen manyfiles.zip
[   16s] open_many_ok -- FAILED: zip file manyfiles.zip wrong
Comment 5 Petr Gajdos 2017-09-05 12:04:50 UTC
1.3.0 testsuite fails with:

[   52s] FAIL: set_compression_deflate_to_store
[   52s] ======================================
[   52s]
[   52s] Unexpected exit status:
[   52s] -0
[   52s] +1
[   52s] Unexpected error output:
[   52s] --- expected
[   52s] +++ got
[   52s] +can't close zip archive 'test.zip': Internal error
[   52s] --- ../teststored.zip
[   52s] +++ test.zip
[   52s] ---                     abac-repeat.txt  method 0
[   52s] +++                     abac-repeat.txt  method 8
[   52s] set_compression_deflate_to_store -- FAIL: exit status, error output, files
[   52s] FAIL set_compression_deflate_to_store.test (exit status: 1)


It seems, this does not relate to 12/libzip testsuite failure.
Comment 6 Petr Gajdos 2017-09-05 12:19:51 UTC
For 12/libzip: the reason is:

libzip-0.11.1/src/.libs/zipcmp: cannot open zip archive `../bigzero.zip': Zip archive inconsistent
Comment 7 Petr Gajdos 2017-09-05 12:32:29 UTC
bigzero-zip.zip in 0.11.1 and 1.3.0 is different (https://github.com/nih-at/libzip/commit/9b46957ec98d85a572e9ef98301247f39338a3b5) but updating it in 0.11.1 does not make the testsuite result better.
Comment 8 Petr Gajdos 2017-09-05 13:16:15 UTC
Failing command is:

$ zipcmp -q -p -t bigzero.zip bigzero.zip                                       
zipcmp: cannot open zip archive `bigzero.zip': Zip archive inconsistent
$
Comment 9 Petr Gajdos 2017-09-06 12:00:12 UTC
The reason, why bigzero.zip is rejected is:

-    if ((flags & ZIP_CHECKCONS) && offset+size != eocd_offset) {
+    if ((flags & ZIP_CHECKCONS) && offset+size != buf_offset + eocd_offset) {

(gdb) p offset+size
$7 = 4168331
(gdb) p buf_offset + eocd_offset
$8 = 8271182
(gdb) p buf_offset
$9 = 4102851
(gdb) p eocd_offset
$10 = 4168331

interestingly, offset+size == eocd_offset, so the condition is not met before and is met after.
Comment 10 Petr Gajdos 2017-09-06 12:46:46 UTC
I believe the change for 12/libzip is correct despite two failing tests.

There are many files in regress/ subdirectory (incons*), which are now failing  zip_cmp with 'Zip archive inconsistent'. zip_cmp have not checked the inconsistency properly and would not also for regress/incons* files. I guess bigzero.zip and manyfiles.zip are just also now tagged as inconsistent, which fails zip_cmp and this fails the tests and testsuite in turn.


I will disable these tests.
Comment 11 Petr Gajdos 2017-09-06 13:07:39 UTC
12/libzip submitted.
Comment 12 Petr Gajdos 2017-09-06 13:22:54 UTC
Tumbleweed/libzip:

Fails in add_data(), zip_close.c:
 
461       if ((ret=_zip_dirent_write(za, de, flags)) < 0)
(gdb) 
464       if (is_zip64 != ret) {
(gdb) 
466           zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
(gdb) p is_zip64
$10 = 1
(gdb) p ret
$11 = 0

That means following comment apply:

/* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */

Upstream notified, I will disable the test for now.
Comment 13 Petr Gajdos 2017-09-06 13:25:19 UTC
Packages submitted.
Comment 14 Petr Gajdos 2017-09-06 13:26:01 UTC
.
Comment 15 Bernhard Wiedemann 2017-09-06 14:00:28 UTC
This is an autogenerated message for OBS integration:
This bug (1056996) was mentioned in
https://build.opensuse.org/request/show/521697 Factory / libzip
Comment 17 Bernhard Wiedemann 2017-09-06 16:00:34 UTC
This is an autogenerated message for OBS integration:
This bug (1056996) was mentioned in
https://build.opensuse.org/request/show/521703 Factory / libzip
Comment 18 Andreas Stieger 2017-09-21 18:51:37 UTC
Assigning for 32 bit test failures.
Comment 19 Swamp Workflow Management 2017-09-21 19:15:36 UTC
SUSE-SU-2017:2546-1: An update that fixes one vulnerability is now available.

Category: security (moderate)
Bug References: 1056996
CVE References: CVE-2017-14107
Sources used:
SUSE Linux Enterprise Software Development Kit 12-SP3 (src):    libzip-0.11.1-13.3.1
SUSE Linux Enterprise Software Development Kit 12-SP2 (src):    libzip-0.11.1-13.3.1
SUSE Linux Enterprise Server for Raspberry Pi 12-SP2 (src):    libzip-0.11.1-13.3.1
SUSE Linux Enterprise Server 12-SP3 (src):    libzip-0.11.1-13.3.1
SUSE Linux Enterprise Server 12-SP2 (src):    libzip-0.11.1-13.3.1
SUSE Linux Enterprise Desktop 12-SP3 (src):    libzip-0.11.1-13.3.1
SUSE Linux Enterprise Desktop 12-SP2 (src):    libzip-0.11.1-13.3.1
Comment 20 Swamp Workflow Management 2017-09-21 22:07:36 UTC
openSUSE-SU-2017:2550-1: An update that fixes one vulnerability is now available.

Category: security (moderate)
Bug References: 1056996
CVE References: CVE-2017-14107
Sources used:
openSUSE Leap 42.3 (src):    libzip-0.11.1-9.1
openSUSE Leap 42.2 (src):    libzip-0.11.1-6.3.1
Comment 21 Petr Gajdos 2017-09-22 05:27:38 UTC
(In reply to Andreas Stieger from comment #18)
> Assigning for 32 bit test failures.

This bug seem to be fixed, though.
Comment 22 Bernhard Wiedemann 2017-09-22 08:00:53 UTC
This is an autogenerated message for OBS integration:
This bug (1056996) was mentioned in
https://build.opensuse.org/request/show/528196 Factory / libzip