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#downloadUpdate
to write their contents out of the intended desintination directory/unzipped
.This bug can lead to two potential issues:
/unzipped
directories like/unzipped-private
/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 thecom.microsoft.codepush.react.FileUtils#validateFileName
method 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
destinationFolder
argument, which will always be a directory ending in/unzipped
, but thefileName
comes 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