Skip to content

Improper Limitation of a Pathname to a Restricted Directory ('Partial-Path Traversal') during unzip in react-native-code-push

High
JLLeitschuh published GHSA-7hfp-mpq6-2jhf May 16, 2022

Package

npm react-native-code-push (npm)

Affected versions

<=v7.0.4

Patched versions

None

Description

Impact

Partial-path traversal vulnerability allows zip files downloaded as a part of the com.microsoft.codepush.react.CodePushNativeModule#downloadUpdate to write their contents out of the intended desintination directory /unzipped.

This bug can lead to two potential issues:

  • Arbitrarily written files to sibling directories of the /unzipped directories like /unzipped-private
  • DOS of the host system by filling the disk space of the drive as these files written outside the /unzipped directories will never be cleaned up.

The downloadUpdate method, although written in Java, is exposed as a react-native method, and is invoked from Javascript code.

Vulnerability Root Cause

The com.microsoft.codepush.react.FileUtils#unzipFile contains a partial-path traversal vulnerability in the logic used to unzip a zip file. This is due to the com.microsoft.codepush.react.FileUtils#validateFileName method containing an insufficient guard against partial-path traversal vulnerabilities.

   private static String validateFileName(String fileName, File destinationFolder) throws IOException {
       String destinationFolderCanonicalPath = destinationFolder.getCanonicalPath();

       File file = new File(destinationFolderCanonicalPath, fileName);
       String canonicalPath = file.getCanonicalPath();

       if (!canonicalPath.startsWith(destinationFolderCanonicalPath)) {
           throw new IllegalStateException("File is outside extraction target directory.");
       }

       return canonicalPath;
   }

- https://github.com/microsoft/react-native-code-push/blob/f72751fbc044e8348bda82c52b784d29952e06dd/android/app/src/main/java/com/microsoft/codepush/react/FileUtils.java#L126-L137

The application controls the destinationFolder argument, which will always be a directory ending in /unzipped, but the fileName comes from the untrusted Zip file. The above bit of logic can be bypassed with the following payloads:

// The following will return the string "[SOME PARENT PATH]/unzipped-private/foo-bar"
validateFileName("/../unzipped-private/foo-bar", new File("[SOME PARENT PATH]/unzipped"))

True Root cause

If the result of parent.getCanonicalPath() is not slash terminated it allows for partial path traversal.

Consider "/usr/outnot".startsWith("/usr/out"). The check is bypassed although outnot is not under the out directory.
The terminating slash may be removed in various places. On Linux println(new File("/var/")) returns /var, but println(new File("/var", "/")) - /var/, however println(new File("/var", "/").getCanonicalPath()) - /var.
- @JarLob (Jaroslav Lobačevski)

Patches

None

Workarounds

None

References

Similar vulnerabilities:

Response from Microsoft

VULN-066991 CRM:0765000224

Hello,

Thank you for contacting the Microsoft Security Response Center (MSRC). We appreciate the time taken to submit this assessment.

Upon investigation, we have determined that this submission does not meet the definition of a security vulnerability for servicing. This report does not appear to identify a weakness in a Microsoft product or service that would enable an attacker to compromise the integrity, availability, or confidentiality of a Microsoft offering.

As such, this thread is being closed and no longer monitored. We apologize for any inconvenience this may have caused.

If you believe this determination to be in error, submit a new report at https://aka.ms/secure-at

Please include:

Relevant information previously provided in your initial report
Detailed steps required to consistently reproduce the issue
Short explanation on how an attacker could use the information to exploit another user remotely
Proof-of-concept (POC), such as a video recording, crash reports, screenshots, or relevant code samples

More information on reporting a security vulnerability can be found at https://www.microsoft.com/msrc/faqs-report-an-issue.

Regards,

Ali 
MSRC

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
High
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H

CVE ID

No known CVE

Weaknesses

Credits