Severe Security Vulnerability in Bower’s Zip Archive Extraction

January 31, 2019 | in Vulnerabilities
| By Liran Tal

Earlier this month it was found that Bower, a popular web package manager, is vulnerable to archive extractions and currently, we can associate two security incidents with it, for which follow-up releases to address them are available:

  • Arbitrary file writes with potential remote command execution, which was fixed in Bower 1.8.6, resulted from the Zip Slip vulnerabilities found in the decompress-zip dependency, an open source dependency used by Bower.
  • Arbitrary file writes caused by .tar.gz archive symbolic link (symlink) vulnerabilities that are exploited because of how Bower extracts such archives, was fixed in Bower 1.8.8.

Webpack, yarn, and the npm registry may have changed the game for Bower but it is still being used. Even though there are more popular package managers nowadays and npm being the de-facto registry for JavaScript, Bower is still very heavily relied-upon as a package manager, with almost 2 million downloads a month, highlighting the severity of such a security issue.

On January 1st 2019, a security researcher called skyn3t, reported to the Node.js security working group on HackerOne an arbitrary file write implemented through improper validation of symlinks resulting from the way Bower handles tar archive extraction.

Shortly after the bug had been triaged, Adam Stankiewicz from Bower’s core team was invited to review the report and promptly confirmed it, providing a fix in the Bower 1.8.8 release to address the security concern.

Malicious path traversal in archive extraction

If a malicious actor were to create a specially crafted zip archive for a package that was then installed with Bower, it could result in path traversal so that files would get extracted outside the root directory that is expected to unwrap the archive.

The following Proof of Concept (POC) originates from a security report that was disclosed by skyn3t to the Node.js security working group program on HackerOne, and shows how insecure handling of symlinks may result in arbitrary file writes.

The malicious package archive

The archive needs to create a symlink to a directory and then land a file in that target directory, but in order to replicate this directory layout we need to hand-craft a malicious archive.

We will start off by creating a directory for the malicious package, a default package.json file for Bower, and a symlink to /tmp:

mkdir malicious-package
cd malicious-package
npm init -y
ln -s /tmp mySpecialDirectory

Now we can create a tarball archive for this package, and make sure not to compress it:

tar -cvf malicious-package.tar malicious-package

Crafting a malicious tar archive with symlink to system directories

The tricky part is getting a file of our control into the /tmp directory and essentially into mySpecialDirectory/ inside the archive. That filename is already taken as a link, so we can’t just re-use it on our own filesystem.

To overcome this challenge, we revert back to standard core archive functionality – manipulating data within the archive. tar files allow us to update an existing archive, such as adding more files to it, enabling us to create an escape hatch.

We’ll go ahead and delete the link, create a directory in place of it and create our own file inside of it. Then we will add just that file into the archive with the tar update functionality:

rm mySpecialDirectory
mkdir mySpecialDirectory
echo “abc” > mySpecialDirectory/ssmaliciousFile
cd ..
tar -rvf malicious-package.tar malicious-package/mySpecialDirectory/ssmaliciousFile

As can be seen in the screenshot, the contents of the archive include a symlink to the /tmp directory as well as to a malicious file that we’ve created:

Crafting a malicious tar archive with symlink to system directories

It’s important to note that compressed archives can’t be manipulated the same way that tar archives can. Therefore, we’ll perform the gzip compression now that the archive has been maliciously crafted:

gzip malicious-package.tar

Triggering Bower to install

Now that we have a tar.gz archive in the home folder directory ~/tmp let’s execute a Bower installation from the local file system in order to demonstrate how the package unravels:

Bower package manager extracting malicious zip archive

As can be seen, Bower 1.8.7 is used and upon installing the malicious package the malicious file that was in our control was subsequently installed in the system’s /tmp directory.

Addressing the vulnerability

Bower supports these archive types: tar, tar.gz and zip. While a similar vulnerability affecting zip packages was already solved by fixing decompress-zip, tar and tar.gz remained vulnerable.

The applied fix that was ultimately offered for the tar and tar.gz vulnerabilities mitigated the issue by ignoring any symlinks in packages to be installed, and a new Bower version has since been released as 1.8.8 for users to upgrade to and mitigate the security issue.

Earlier in 2018, the Snyk security research team had coined the Zip Slip security vulnerability term after conducting widespread research for archive extraction exploitation that results in arbitrary file writes. A critical severity may further result in remote command execution and overwriting sensitive system configuration files.

The Zip Slip research resulted in the discovery of thousands of projects that were vulnerable, across many ecosystems, and affecting projects from Apache, Pivotal, Amazon, and others.

In summary

We’ve seen how to create a deliberate malicious package that can cause an arbitrary file write, but the problem doesn’t rest just with malicious packages being downloaded. If a package is fetched over an insecure medium, such as non-HTTPS traffic, then a man-in-the-middle attack can be employed.

Issues with extracting files aren’t new and might actually date all the way back to a Phrack article in 1991 that explained how to hack a BBS by employing such zip extraction attack vectors. We will most likely continue to see Zip Slip vulnerabilities being discovered in libraries and applications as more research is conducted in this field.

Remember that even though symlinks are allowed, working with user-controlled archives is dangerous and should be handled with due-diligence just like with any other user input.

 

Takeaways

  • Upgrade to Bower 1.8.8 as soon as possible.
  • You’re invited to consult our Zip Slip Cheat Sheet for references of vulnerable code in different language ecosystems and how to avoid similar security vulnerabilities in your code.