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
Impact
Partial-path traversal vulnerability allows zip files downloaded as a part of the
com.microsoft.codepush.react.CodePushNativeModule#downloadUpdateto write their contents out of the intended desintination directory/unzipped.This bug can lead to two potential issues:
/unzippeddirectories like/unzipped-private/unzippeddirectories will never be cleaned up.The
downloadUpdatemethod, 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#unzipFilecontains a partial-path traversal vulnerability in the logic used to unzip a zip file. This is due to thecom.microsoft.codepush.react.FileUtils#validateFileNamemethod containing an insufficient guard against partial-path traversal vulnerabilities.- 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
destinationFolderargument, which will always be a directory ending in/unzipped, but thefileNamecomes from the untrusted Zip file. The above bit of logic can be bypassed with the following payloads:True Root cause
Patches
None
Workarounds
None
References
Similar vulnerabilities:
Response from Microsoft