Summary
ZipSecurity#isBelowCurrentDirectory is vulnerable to a partial-path traversal bypass.
Impact
To be vulnerable to the bypass, the following conditions must all be met:
- Applications that uses toolkit version <=1.1.1
- Applications that uses
ZipSecurity as a guard against path traversal
- Applications that have a exploit path
Although the control still protects attackers from escaping the application path into higher level directories (e.g., /etc/), it will allow "escaping" into sibling paths.
For example, if your running path is /my/app/path you an attacker could navigate into /my/app/path-something-else.
Details
See:
|
boolean isBelowCurrentDirectory(final File fileWithEscapes) throws IOException { |
|
final File currentDirectory = new File(""); |
|
String canonicalizedTargetPath = fileWithEscapes.getCanonicalPath(); |
|
String canonicalizedCurrentPath = currentDirectory.getCanonicalPath(); |
|
return !canonicalizedTargetPath.startsWith(canonicalizedCurrentPath); |
|
} |
This method is vulnerable because currentDirectory.getCanonicalPath() returns a string that is not terminated by a trailing slash. As such, using startsWith to do string comparisons opens up a weakness allowing for partial-path traversal into a sibling directory.
PoC
This vulnerability is described in detail in Jonathan Leitschuh's Black Hat talk: https://youtu.be/zTtbVxGEq8A?si=Nmt0aGpPnSPrzTxi
Assume that the working directory for the given Java process is a directory named code-sandbox. The following test demonstrates escaping that directory.
@Test
void pixeeZipGuardBypass() throws IOException {
File bypass = new File("../code-sandbox-sibling/bypass");
assertTrue(isBelowCurrentDirectory(bypass), "The attacker provided value escaped the intended directory!");
}
boolean isBelowCurrentDirectory(final File fileWithEscapes) throws IOException {
final File currentDirectory = new File("");
String canonicalizedTargetPath = fileWithEscapes.getCanonicalPath();
String canonicalizedCurrentPath = currentDirectory.getCanonicalPath();
return !canonicalizedTargetPath.startsWith(canonicalizedCurrentPath);
}
Credit
Thanks to Jonathan Leitschuh for discovering and reporting the vulnerability.
Summary
ZipSecurity#isBelowCurrentDirectoryis vulnerable to a partial-path traversal bypass.Impact
To be vulnerable to the bypass, the following conditions must all be met:
ZipSecurityas a guard against path traversalAlthough the control still protects attackers from escaping the application path into higher level directories (e.g.,
/etc/), it will allow "escaping" into sibling paths.For example, if your running path is
/my/app/pathyou an attacker could navigate into/my/app/path-something-else.Details
See:
java-security-toolkit/src/main/java/io/github/pixee/security/ZipSecurity.java
Lines 82 to 87 in 7c8e93e
This method is vulnerable because
currentDirectory.getCanonicalPath()returns a string that is not terminated by a trailing slash. As such, usingstartsWithto do string comparisons opens up a weakness allowing for partial-path traversal into a sibling directory.PoC
This vulnerability is described in detail in Jonathan Leitschuh's Black Hat talk: https://youtu.be/zTtbVxGEq8A?si=Nmt0aGpPnSPrzTxi
Assume that the working directory for the given Java process is a directory named
code-sandbox. The following test demonstrates escaping that directory.Credit
Thanks to Jonathan Leitschuh for discovering and reporting the vulnerability.