Hi,
InfoZIP unzip 6.0 contains a heap out-of-bounds read in the
ef_scan_for_izux() function in process.c when processing EF_IZUNIX3
(ID 0x7875) extra field blocks. This is a missed variant of
CVE-2014-8139 — that fix addressed the EF_IZUNIX (0x5855) and
EF_IZUNIX2 (0x7855) handlers but did NOT patch the EF_IZUNIX3 (0x7875)
handler.
CAN: CAN-2026-2034440 (pending assignment from MITRE)
CWE: CWE-125 (Out-of-bounds Read)
CVSS: 6.1 Medium
ROOT CAUSE (process.c, line 2988):
uid_size = *((EB_HEADSIZE + 1) + ef_buf);
gid_size = *((EB_HEADSIZE + uid_size + 2) + ef_buf); // OOB READ
The only validation is `eb_len >= EB_UX3_MINLEN` (i.e., eb_len >= 7).
uid_size is attacker-controlled (a byte value 0-255, read from ef_buf
at a fixed offset). With uid_size=200 and eb_len=7, the gid_size read
at offset (EB_HEADSIZE + 200 + 2) = 206 reads 199 bytes past the end
of the 7-byte extra field data. The subsequent read_ux3_value() calls
at offsets (EB_HEADSIZE + 2) and (EB_HEADSIZE + uid_size + 3) compound
the over-read.
TRIGGER: unzip -o poc.zip (extraction mode) where poc.zip contains a
file entry with an EF_IZUNIX3 extra field block with eb_len=7 and
uid_size=200.
ASAN OUTPUT (Debian unzip 6.0, built with -fsanitize=address
-DIZ_HAVE_UXUIDGID):
==12==ERROR: AddressSanitizer: heap-buffer-overflow on address
0xffffafe007de at pc 0xaaaae3888d50
READ of size 1 at 0xffffafe007de thread T0
#0 ef_scan_for_izux /build/unzip-6.0/process.c:2988:28
#1 get_extattribs /build/unzip-6.0/unix/unix.c:1063:36
#2 close_outfile /build/unzip-6.0/unix/unix.c:1115:23
#3 extract_or_test_member /build/unzip-6.0/extract.c:2122:9
#4 extract_or_test_entrylist /build/unzip-6.0/extract.c:1748:22
#5 extract_or_test_files /build/unzip-6.0/extract.c:741:17
IMPACT: Heap OOB read causing crash (DoS). The OOB-read value is used
as a UID for chown() on the extracted file, so an attacker can also
influence file ownership. Active on all distributions that compile with
-DIZ_HAVE_UXUIDGID (Debian, Ubuntu, Red Hat, SUSE).
SUGGESTED FIX (add bounds checks matching the CVE-2014-8139 pattern):
uid_size = *((EB_HEADSIZE + 1) + ef_buf);
+ if (uid_size + 3 > eb_len)
+ break;
gid_size = *((EB_HEADSIZE + uid_size + 2) + ef_buf);
+ if (uid_size + gid_size + 3 > eb_len)
+ break;
Best regards,
Akhil Koul