Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,30 @@ private UnsafePathChecker() {}
"c:\\"
);

public static boolean startsWithUnsafePath(String filePath) {
String lowerCasePath = filePath.toLowerCase();
public static boolean startsWithUnsafePath(String filePathRaw) {
Comment thread
bitterpanda63 marked this conversation as resolved.
String filePath = ensureOneLeadingSlash(filePathRaw.toLowerCase());

List<String> dangerousStartsList = new ArrayList<>(DANGEROUS_PATH_STARTS);
dangerousStartsList.addAll(LINUX_ROOT_FOLDERS);

for (String dangerousStart : dangerousStartsList) {
if (lowerCasePath.startsWith(dangerousStart)) {
if (filePath.startsWith(dangerousStart)) {
return true;
}
}
return false;
}
public static boolean startsWithUnsafePath(String filePath, String userInput) {
String filePathLowercase = filePath.toLowerCase();
String userinputLowercase = userInput.toLowerCase();
return startsWithUnsafePath(filePathLowercase) && filePathLowercase.startsWith(userinputLowercase);

public static boolean startsWithUnsafePath(String filePathRaw, String userInputRaw) {
String filePath = ensureOneLeadingSlash(filePathRaw.toLowerCase());
String userInput = ensureOneLeadingSlash(userInputRaw.toLowerCase());
return startsWithUnsafePath(filePath) && filePath.startsWith(userInput);
}

private static String ensureOneLeadingSlash(String path) {
Comment thread
bitterpanda63 marked this conversation as resolved.
if (path.startsWith("/")) {
return "/" + path.replaceAll("^/+", "");
}
return path;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,11 @@ public void testEdgeCases() {
assertTrue(UnsafePathChecker.startsWithUnsafePath("c:/", "c:/"));
assertTrue(UnsafePathChecker.startsWithUnsafePath("c:/folder/file.txt", "c:/folder"));
}

@Test
public void testMultipleSlashes() {
assertTrue(UnsafePathChecker.startsWithUnsafePath("///etc///passwd", "///etc//"));
assertTrue(UnsafePathChecker.startsWithUnsafePath("///etc/passwd", "///etc"));
assertFalse(UnsafePathChecker.startsWithUnsafePath("etc/passwd///../test.txt", "etc/passwd///../test.txt"));
}
}
59 changes: 57 additions & 2 deletions agent_api/src/test/java/wrappers/FileWrapperTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@

import java.io.File;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
Expand Down Expand Up @@ -41,7 +45,7 @@ public void testPathTraversalString() throws Exception {
assertThrows(RuntimeException.class, () -> {
new File("/var/../file.txt");
});

cleanup();
assertDoesNotThrow(() -> {
new File("/var/../file.txt");
Expand Down Expand Up @@ -88,4 +92,55 @@ public void testPathTraversalMultiple() throws Exception {
new File("/etc/", "/var/../file.txt");
});
}
}

@Test
public void testOsCreatePathWithMultipleSlashes() {
String filePath = "/////etc/passwd";
setContextAndLifecycle(filePath);
assertThrows(RuntimeException.class, () -> {
Path fullPath = Paths.get(filePath);
List<String> lines = Files.readAllLines(fullPath);
System.err.println(lines);
});
}

@Test
public void testOsCreatePathWithMultipleSlashesNegative() {
String filePath = "safe/relative/path";
setContextAndLifecycle(filePath);
assertDoesNotThrow(() -> {
File fullPath = new File("flaskr/resources/blogs/", filePath);
fullPath.exists(); // Simulate access
});
}

@Test
public void testOsCreatePathWithMultipleDoubleSlashes() {
String filePath = "////etc//passwd";
setContextAndLifecycle(filePath);
assertThrows(RuntimeException.class, () -> {
File fullPath = new File("flaskr/resources/blogs/", filePath);
fullPath.exists(); // Simulate access
});
}

@Test
public void testOsCreatePathWithMultipleDoubleSlashesNegative() {
String filePath = "safe//relative//path";
setContextAndLifecycle(filePath);
assertDoesNotThrow(() -> {
File fullPath = new File("flaskr/resources/blogs/", filePath);
fullPath.exists(); // Simulate access
});
}

@Test
public void testOsPathTraversalWithMultipleSlashes() {
String filePath = "home///..////..////my_secret.txt";
setContextAndLifecycle(filePath);
assertThrows(RuntimeException.class, () -> {
File fullPath = new File("flaskr/resources/blogs/", filePath);
fullPath.exists(); // Simulate access
});
}
}
Loading