Skip to content
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

Heap-buffer-overflow in mz_os.c:188 in mz_path_resolve #740

Closed
Akane0721 opened this issue Nov 8, 2023 · 5 comments
Closed

Heap-buffer-overflow in mz_os.c:188 in mz_path_resolve #740

Akane0721 opened this issue Nov 8, 2023 · 5 comments
Labels
bug Bug fixed Issue or bug has been fixed security Security issue

Comments

@Akane0721
Copy link

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
@nmoinvaz nmoinvaz added the help wanted Need outside help label Nov 8, 2023
@pmqs
Copy link
Contributor

pmqs commented Nov 8, 2023

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 . 
#

@Akane0721
Copy link
Author

Akane0721 commented Nov 9, 2023

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?

@pmqs
Copy link
Contributor

pmqs commented Nov 9, 2023

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

@pmqs
Copy link
Contributor

pmqs commented Nov 12, 2023

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
nmoinvaz pushed a commit that referenced this issue Nov 13, 2023
@nmoinvaz nmoinvaz added bug Bug fixed Issue or bug has been fixed security Security issue and removed help wanted Need outside help labels Nov 13, 2023
@nmoinvaz
Copy link
Member

Fixed in 4.0.3. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Bug fixed Issue or bug has been fixed security Security issue
Projects
None yet
Development

No branches or pull requests

3 participants