Headline
CVE-2023-48106: Heap-buffer-overflow in mz_os.c:188 in mz_path_resolve · Issue #740 · zlib-ng/minizip-ng
Buffer Overflow vulnerability in zlib-ng minizip-ng v.4.0.2 allows an attacker to execute arbitrary code via a crafted file to the mz_path_resolve function in the mz_os.c file.
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Akane0721 opened this issue
Nov 8, 2023
· 5 comments
Comments
Description
heap-buffer-overflow (/minizip-ng/build/minizip+0x976d) in mz_path_resolve
Version
$ ./minizip -h minizip-ng 4.0.2 - https://github.com/zlib-ng/minizip-ng
-h Usage: minizip [-x][-d dir|-l|-e][-o][-f][-y][-c cp][-a][-0 to -9][-b|-m|-t][-k 512][-p pwd][-s] file.zip [files]
-x Extract files -l List files -d Destination directory -e Erase files -o Overwrite existing files -c File names use cp437 encoding (or specified codepage) -a Append to existing zip file -i Include full path of files -f Follow symbolic links -y Store symbolic links -v Verbose info -0 Store only -1 Compress faster -9 Compress better -k Disk size in KB -z Zip central directory -p Encryption password -s AES encryption -b BZIP2 compression -m LZMA compression -n XZ compression -t ZSTD compression
Replay
git clone https://github.com/zlib-ng/minizip-ng.git cd minizip-ng/ CC="gcc -fsanitize=address" CXX="g++ -fsanitize=address" cmake -S . -B build -D MZ_BUILD_TESTS=ON cmake --build build ./minizip -x -o poc1
ASAN
-x -o /root/poc/minizip/poc1 Archive /root/poc/minizip/poc1 ================================================================= ==3028155==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60d0000001df at pc 0x55555555d76e bp 0x7fffffffddf0 sp 0x7fffffffdde0 READ of size 1 at 0x60d0000001df thread T0 #0 0x55555555d76d in mz_path_resolve (/root/test/minizip-ng/build/minizip+0x976d) #1 0x555555573c77 in mz_zip_reader_save_all (/root/test/minizip-ng/build/minizip+0x1fc77) #2 0x55555555af70 in minizip_extract (/root/test/minizip-ng/build/minizip+0x6f70) #3 0x55555555c7ec in main (/root/test/minizip-ng/build/minizip+0x87ec) #4 0x7ffff73a9082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) #5 0x555555558aed in _start (/root/test/minizip-ng/build/minizip+0x4aed)
0x60d0000001df is located 1 bytes to the left of 129-byte region [0x60d0000001e0,0x60d000000261) allocated by thread T0 here: #0 0x7ffff76a0808 in __interceptor_malloc …/…/…/…/src/libsanitizer/asan/asan_malloc_linux.cc:144 #1 0x55555557391b in mz_zip_reader_save_all (/root/test/minizip-ng/build/minizip+0x1f91b) #2 0x55555555af70 in minizip_extract (/root/test/minizip-ng/build/minizip+0x6f70) #3 0x55555555c7ec in main (/root/test/minizip-ng/build/minizip+0x87ec) #4 0x7ffff73a9082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
SUMMARY: AddressSanitizer: heap-buffer-overflow (/root/test/minizip-ng/build/minizip+0x976d) in mz_path_resolve Shadow bytes around the buggy address: 0x0c1a7fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c1a7fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c1a7fff8000: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00 0x0c1a7fff8010: 00 00 00 00 00 00 00 00 01 fa fa fa fa fa fa fa 0x0c1a7fff8020: fa fa 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x0c1a7fff8030: 00 00 01 fa fa fa fa fa fa fa fa[fa]00 00 00 00 0x0c1a7fff8040: 00 00 00 00 00 00 00 00 00 00 00 00 01 fa fa fa 0x0c1a7fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c1a7fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c1a7fff8070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c1a7fff8080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb Shadow gap: cc ==3028155==ABORTING
POC
https://github.com/Akane0721/POC/blob/f37d805631e0a15bea1f15b6e1edfb3246a2e0fc/minizip-ng/poc1
Environment
Ubuntu 20.04
Clang 10.0.0
gcc 9.4.0
Where did poc1 come from? It is a badly corrupted zip file
minizip doesn’t complain about it
$ ./minizip -l poc1
minizip-ng 4.0.1 - https://github.com/zlib-ng/minizip-ng
---------------------------------------------------
-l poc1
Packed Unpacked Ratio Method Attribs Date Time CRC-32 Name
------ -------- ----- ------ ------- ---- ---- ------ ----
805503117 2018794583 39% deflate 0 11-07-14 04:30 f0c14f39 l//../////////////0W/T/.�TU//�
But this is what unzip thinks about it
$ unzip -l poc1
Archive: poc1
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
unzip: cannot find zipfile directory in one of poc1 or
poc1.zip, and cannot find poc1.ZIP, period.
same with 7z
$ 7z l ~/Downloads/poc1
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_GB.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz (506E3),ASM,AES-NI)
Scanning the drive for archives:
1 file, 253 bytes (1 KiB)
Listing archive: /home/paul/Downloads/poc1
ERROR: /home/paul/Downloads/poc1 : Can not open the file as archive
Errors: 1
the file appears to have a single local header that contains some crazy values.
0000 0003 0004 50 4B 03 04 LOCAL HEADER #1 04034B50 (67324752)
0004 0004 0001 14 Extract Zip Spec 14 (20) '2.0'
0005 0005 0001 00 Extract OS 00 (0) 'MS-DOS'
0006 0007 0002 02 ED General Purpose Flag ED02 (60674)
[Bits 1-2] 1 'Maximum Compression'
[Bit 11] 1 'Language Encoding'
[Bit 13] 1 'Encrypted Central Dir'
0008 0009 0002 08 00 Compression Method 0008 (8) 'Deflated'
000A 000D 0004 DC 23 67 45 Last Mod Time 456723DC (1164387292) 'Fri Nov 7 04:30:56 2014'
000E 0011 0004 39 4F C1 F0 CRC F0C14F39 (4039200569)
0012 0015 0004 8D 00 03 30 Compressed Length 3003008D (805503117)
0016 0019 0004 57 5C 54 78 Uncompressed Length 78545C57 (2018794583)
001A 001B 0002 78 00 Filename Length 0078 (120)
001C 001D 0002 00 00 Extra Length 0000 (0)
#
# WARNING: Offset 0x1E: Could not decode 'utf8' Filename: utf8 "\x81" does not map to Unicode
#
001E 0095 0078 6C 2F 2F 2E Filename 'l//../////////////0W\T\.TU// Ô ¿ nwGF¯ÀÑIí Ü#gE9OÁð CW\meri!kUTTUx limer C Èÿ mÊG
2E 2F 2F 2F U\nè ¶Í`eÒfÿ ,8'
2F 2F 2F 2F
2F 2F 2F 2F
2F 2F 30 57
5C 54 5C 2E
81 54 55 2F
2F 01 D4 01
00 BF 00 00
00 6E 77 47
46 AF C0 95
D1 49 ED 08
00 DC 23 67
45 39 4F C1
F0 8D 00 03
43 57 5C 6D
65 72 69 21
6B 55 54 54
55 78 00 00
00 6C 69 6D
65 72 03 43
00 00 00 C8
FF 7F 8D 9E
E4 6D 8C CA
47 8D 00 00
00 8A 55 5C
98 BA 6E E8
03 B6 CD 60
65 D2 66 FF
7F 09 2C 38
#
# FATAL: Offset 0x96: file truncated while reading 'PAYLOAD'
# Expected 0x3003008D bytes, but only 0x67 available .
#
Where did poc1 come from? It is a badly corrupted zip file
minizip doesn’t complain about it
$ ./minizip -l poc1 minizip-ng 4.0.1 - https://github.com/zlib-ng/minizip-ng --------------------------------------------------- -l poc1 Packed Unpacked Ratio Method Attribs Date Time CRC-32 Name ------ -------- ----- ------ ------- ---- ---- ------ ---- 805503117 2018794583 39% deflate 0 11-07-14 04:30 f0c14f39 l//../////////////0W/T/.�TU//�
But this is what unzip thinks about it
$ unzip -l poc1 Archive: poc1 End-of-central-directory signature not found. Either this file is not a zipfile, or it constitutes one disk of a multi-part archive. In the latter case the central directory and zipfile comment will be found on the last disk(s) of this archive. unzip: cannot find zipfile directory in one of poc1 or poc1.zip, and cannot find poc1.ZIP, period.
same with 7z
$ 7z l ~/Downloads/poc1 7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21 p7zip Version 16.02 (locale=en_GB.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz (506E3),ASM,AES-NI) Scanning the drive for archives: 1 file, 253 bytes (1 KiB) Listing archive: /home/paul/Downloads/poc1 ERROR: /home/paul/Downloads/poc1 : Can not open the file as archive Errors: 1
the file appears to have a single local header that contains some crazy values.
0000 0003 0004 50 4B 03 04 LOCAL HEADER #1 04034B50 (67324752) 0004 0004 0001 14 Extract Zip Spec 14 (20) '2.0' 0005 0005 0001 00 Extract OS 00 (0) 'MS-DOS' 0006 0007 0002 02 ED General Purpose Flag ED02 (60674) [Bits 1-2] 1 'Maximum Compression' [Bit 11] 1 'Language Encoding' [Bit 13] 1 'Encrypted Central Dir' 0008 0009 0002 08 00 Compression Method 0008 (8) 'Deflated' 000A 000D 0004 DC 23 67 45 Last Mod Time 456723DC (1164387292) 'Fri Nov 7 04:30:56 2014' 000E 0011 0004 39 4F C1 F0 CRC F0C14F39 (4039200569) 0012 0015 0004 8D 00 03 30 Compressed Length 3003008D (805503117) 0016 0019 0004 57 5C 54 78 Uncompressed Length 78545C57 (2018794583) 001A 001B 0002 78 00 Filename Length 0078 (120) 001C 001D 0002 00 00 Extra Length 0000 (0) # # WARNING: Offset 0x1E: Could not decode 'utf8' Filename: utf8 "\x81" does not map to Unicode # 001E 0095 0078 6C 2F 2F 2E Filename 'l//../////////////0W\T\.TU// Ô ¿ nwGF¯ÀÑIí Ü#gE9OÁð CW\meri!kUTTUx limer C Èÿ mÊG 2E 2F 2F 2F U\nè ¶Í`eÒfÿ ,8' 2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 30 57 5C 54 5C 2E 81 54 55 2F 2F 01 D4 01 00 BF 00 00 00 6E 77 47 46 AF C0 95 D1 49 ED 08 00 DC 23 67 45 39 4F C1 F0 8D 00 03 43 57 5C 6D 65 72 69 21 6B 55 54 54 55 78 00 00 00 6C 69 6D 65 72 03 43 00 00 00 C8 FF 7F 8D 9E E4 6D 8C CA 47 8D 00 00 00 8A 55 5C 98 BA 6E E8 03 B6 CD 60 65 D2 66 FF 7F 09 2C 38 # # FATAL: Offset 0x96: file truncated while reading 'PAYLOAD' # Expected 0x3003008D bytes, but only 0x67 available . #
poc1 is a malformed zip file generated by fuzzer. I used the "-x" flag when testing and it came into a heap-buffer-overflow crash. So maybe you could give a proper prompt when using "-x" to extract malformed files like poc1?
poc1 is a malformed zip file generated by fuzzer. I used the "-x" flag when testing and it came into a heap-buffer-overflow crash. So maybe you could give a proper prompt when using "-x" to extract malformed files like poc1?
ok.
Running without ASAN triggers a core. Never a good thing to do
$ ./minizip -x poc1
minizip-ng 4.0.2 - https://github.com/zlib-ng/minizip-ng
---------------------------------------------------
-x poc1
Archive poc1
Extracting l//../////////////0W/T/.�TU//�
double free or corruption (out)
Aborted (core dumped)
When I build with ASAN I see the line numbers where the issue is triggered
$ ./minizip -x -o poc1
minizip-ng 4.0.2 - https://github.com/zlib-ng/minizip-ng
---------------------------------------------------
-x -o poc1
Archive poc1
=================================================================
==49454==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60d0000001df at pc 0x55f2bdfcdfec bp 0x7ffd97501c40 sp 0x7ffd97501c30
READ of size 1 at 0x60d0000001df thread T0
#0 0x55f2bdfcdfeb in mz_path_resolve /home/paul/git/minizip-ng/mz_os.c:188
#1 0x55f2bdfe577b in mz_zip_reader_save_all /home/paul/git/minizip-ng/mz_zip_rw.c:883
#2 0x55f2bdfcb6f0 in minizip_extract /home/paul/git/minizip-ng/minizip.c:379
#3 0x55f2bdfcd02c in main /home/paul/git/minizip-ng/minizip.c:654
#4 0x7f874d2280cf in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#5 0x7f874d228188 in __libc_start_main_impl ../csu/libc-start.c:360
#6 0x55f2bdfc9264 in _start (/home/paul/git/minizip-ng/build/minizip+0x7264) (BuildId: 576262a7c293cbb21845b25bd97a13cb33d9dd27)
0x60d0000001df is located 1 bytes before 129-byte region [0x60d0000001e0,0x60d000000261)
allocated by thread T0 here:
#0 0x7f874dcddde0 in __interceptor_realloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:85
#1 0x55f2bdfe548d in mz_zip_reader_save_all /home/paul/git/minizip-ng/mz_zip_rw.c:861
#2 0x55f2bdfcb6f0 in minizip_extract /home/paul/git/minizip-ng/minizip.c:379
#3 0x55f2bdfcd02c in main /home/paul/git/minizip-ng/minizip.c:654
#4 0x7f874d2280cf in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/paul/git/minizip-ng/mz_os.c:188 in mz_path_resolve
Shadow bytes around the buggy address:
0x60cfffffff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x60cfffffff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x60d000000000: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
0x60d000000080: 00 00 00 00 00 00 00 00 01 fa fa fa fa fa fa fa
0x60d000000100: fa fa 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x60d000000180: 00 00 01 fa fa fa fa fa fa fa fa[fa]00 00 00 00
0x60d000000200: 00 00 00 00 00 00 00 00 00 00 00 00 01 fa fa fa
0x60d000000280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x60d000000300: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x60d000000380: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x60d000000400: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==49454==ABORTING
The issue with this one is a filename of the form x/…/fred. The code in mz_path_resolve tries to remove the … by walking backwards to the preceding /. It wants to end up with the filename fred, but in this case there isn’t a preceeding /, so it walks past the start of the buffer.
See test1.zip for small zip that reproduces the issue.
pmqs added a commit to pmqs/minizip-ng that referenced this issue
Nov 12, 2023
pmqs mentioned this issue
Nov 12, 2023
nmoinvaz pushed a commit that referenced this issue
Nov 13, 2023
nmoinvaz added a commit that referenced this issue
Nov 13, 2023
Fixed in 4.0.3. Thank you!