mirror of
https://github.com/github/codeql.git
synced 2025-12-17 09:13:20 +01:00
864 lines
29 KiB
Java
864 lines
29 KiB
Java
import java.io.File;
|
|
import java.net.URI;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.Paths;
|
|
import android.net.Uri;
|
|
|
|
public class Test {
|
|
|
|
Object source() {
|
|
return null;
|
|
}
|
|
|
|
void sink(Object o) {}
|
|
|
|
private void exactPathMatchGuardValidation(String path) throws Exception {
|
|
if (!path.equals("/safe/path"))
|
|
throw new Exception();
|
|
}
|
|
|
|
public void exactPathMatchGuard() throws Exception {
|
|
{
|
|
String source = (String) source();
|
|
if (source.equals("/safe/path"))
|
|
sink(source); // Safe
|
|
else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
if ("/safe/path".equals(source))
|
|
sink(source); // Safe
|
|
else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
URI source = (URI) source();
|
|
if (source.equals(new URI("http://safe/uri")))
|
|
sink(source); // Safe
|
|
else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
File source = (File) source();
|
|
if (source.equals(new File("/safe/file")))
|
|
sink(source); // Safe
|
|
else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
Uri source = (Uri) source();
|
|
if (source.equals(Uri.parse("http://safe/uri")))
|
|
sink(source); // Safe
|
|
else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
exactPathMatchGuardValidation(source);
|
|
sink(source); // Safe
|
|
}
|
|
}
|
|
|
|
private void allowListGuardValidation(String path) throws Exception {
|
|
if (path.contains("..") || !path.startsWith("/safe"))
|
|
throw new Exception();
|
|
}
|
|
|
|
public void allowListGuard() throws Exception {
|
|
// Prefix check by itself is not enough
|
|
{
|
|
String source = (String) source();
|
|
if (source.startsWith("/safe")) {
|
|
sink(source); // $ hasTaintFlow
|
|
} else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
// PathTraversalGuard + allowListGuard
|
|
{
|
|
String source = (String) source();
|
|
if (!source.contains("..") && source.startsWith("/safe"))
|
|
sink(source); // Safe
|
|
else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
if (source.indexOf("..") == -1 && source.startsWith("/safe"))
|
|
sink(source); // Safe
|
|
else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
if (source.lastIndexOf("..") == -1 && source.startsWith("/safe"))
|
|
sink(source); // Safe
|
|
else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
// PathTraversalSanitizer + allowListGuard
|
|
{
|
|
File source = (File) source();
|
|
String normalized = source.getCanonicalPath();
|
|
if (normalized.startsWith("/safe")) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
File source = (File) source();
|
|
String normalized = source.getCanonicalFile().toString();
|
|
if (normalized.startsWith("/safe")) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
Path normalized = Paths.get(source).normalize();
|
|
if (normalized.startsWith("/safe")) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
String normalized = Paths.get(source).normalize().toString();
|
|
if (normalized.startsWith("/safe")) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
String normalized = Paths.get(source).normalize().toString();
|
|
if (normalized.regionMatches(0, "/safe", 0, 5)) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
String normalized = Paths.get(source).normalize().toString();
|
|
if (normalized.matches("/safe/.*")) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
// validation method
|
|
{
|
|
String source = (String) source();
|
|
allowListGuardValidation(source);
|
|
sink(source); // Safe
|
|
}
|
|
// PathInjectionSanitizer + partial string match is considered unsafe
|
|
{
|
|
String source = (String) source();
|
|
String normalized = Paths.get(source).normalize().toString();
|
|
if (normalized.contains("/safe")) {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
String normalized = Paths.get(source).normalize().toString();
|
|
if (normalized.regionMatches(1, "/safe", 0, 5)) {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
String normalized = Paths.get(source).normalize().toString();
|
|
if (normalized.matches(".*/safe/.*")) {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
}
|
|
|
|
private void dotDotCheckGuardValidation(String path) throws Exception {
|
|
if (!path.startsWith("/safe") || path.contains(".."))
|
|
throw new Exception();
|
|
}
|
|
|
|
public void dotDotCheckGuard() throws Exception {
|
|
// dot dot check by itself is not enough
|
|
{
|
|
String source = (String) source();
|
|
if (!source.contains("..")) {
|
|
sink(source); // $ hasTaintFlow
|
|
} else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
// allowListGuard + dotDotCheckGuard
|
|
{
|
|
String source = (String) source();
|
|
if (source.startsWith("/safe") && !source.contains(".."))
|
|
sink(source); // Safe
|
|
else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
if (source.startsWith("/safe") && source.indexOf("..") == -1)
|
|
sink(source); // Safe
|
|
else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
if (!source.startsWith("/safe") || source.indexOf("..") != -1)
|
|
sink(source); // $ hasTaintFlow
|
|
else
|
|
sink(source); // Safe
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
if (source.startsWith("/safe") && source.lastIndexOf("..") == -1)
|
|
sink(source); // Safe
|
|
else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
// blockListGuard + dotDotCheckGuard
|
|
{
|
|
String source = (String) source();
|
|
if (!source.startsWith("/data") && !source.contains(".."))
|
|
sink(source); // Safe
|
|
else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
if (!source.startsWith("/data") && source.indexOf("..") == -1)
|
|
sink(source); // Safe
|
|
else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
if (source.startsWith("/data") || source.indexOf("..") != -1)
|
|
sink(source); // $ hasTaintFlow
|
|
else
|
|
sink(source); // Safe
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
if (!source.startsWith("/data") && source.lastIndexOf("..") == -1)
|
|
sink(source); // Safe
|
|
else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
// validation method
|
|
{
|
|
String source = (String) source();
|
|
dotDotCheckGuardValidation(source);
|
|
sink(source); // Safe
|
|
}
|
|
}
|
|
|
|
private void blockListGuardValidation(String path) throws Exception {
|
|
if (path.contains("..") || path.startsWith("/data"))
|
|
throw new Exception();
|
|
}
|
|
|
|
public void blockListGuard() throws Exception {
|
|
// Prefix check by itself is not enough
|
|
{
|
|
String source = (String) source();
|
|
if (!source.startsWith("/data")) {
|
|
sink(source); // $ hasTaintFlow
|
|
} else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
// PathTraversalGuard + blockListGuard
|
|
{
|
|
String source = (String) source();
|
|
if (!source.contains("..") && !source.startsWith("/data"))
|
|
sink(source); // Safe
|
|
else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
if (source.indexOf("..") == -1 && !source.startsWith("/data"))
|
|
sink(source); // Safe
|
|
else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
if (source.lastIndexOf("..") == -1 && !source.startsWith("/data"))
|
|
sink(source); // Safe
|
|
else
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
// PathTraversalSanitizer + blockListGuard
|
|
{
|
|
File source = (File) source();
|
|
String normalized = source.getCanonicalPath();
|
|
if (!normalized.startsWith("/data")) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
File source = (File) source();
|
|
String normalized = source.getCanonicalFile().toString();
|
|
if (!normalized.startsWith("/data")) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
Path normalized = Paths.get(source).normalize();
|
|
if (!normalized.startsWith("/data")) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
String normalized = Paths.get(source).normalize().toString();
|
|
if (!normalized.startsWith("/data")) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
String normalized = Paths.get(source).normalize().toString();
|
|
if (!normalized.regionMatches(0, "/data", 0, 5)) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
String normalized = Paths.get(source).normalize().toString();
|
|
if (!normalized.matches("/data/.*")) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
// validation method
|
|
{
|
|
String source = (String) source();
|
|
blockListGuardValidation(source);
|
|
sink(source); // Safe
|
|
}
|
|
// PathInjectionSanitizer + partial string match with disallowed words
|
|
{
|
|
String source = (String) source();
|
|
String normalized = Paths.get(source).normalize().toString();
|
|
if (!normalized.contains("/")) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
String normalized = Paths.get(source).normalize().toString();
|
|
if (!normalized.regionMatches(1, "/", 0, 5)) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
String normalized = Paths.get(source).normalize().toString();
|
|
if (!normalized.matches("/")) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
// PathInjectionSanitizer + partial string match with disallowed prefixes
|
|
{
|
|
String source = (String) source();
|
|
String normalized = Paths.get(source).normalize().toString();
|
|
if (!normalized.contains("/data")) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
String normalized = Paths.get(source).normalize().toString();
|
|
if (!normalized.regionMatches(1, "/data", 0, 5)) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
String normalized = Paths.get(source).normalize().toString();
|
|
if (!normalized.matches(".*/data/.*")) {
|
|
sink(source); // Safe
|
|
sink(normalized); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
}
|
|
|
|
private void fileConstructorValidation(String path) throws Exception {
|
|
// Use `indexOf` instead of `contains` for this test since a `contains`
|
|
// call in this scenario will already be sanitized due to the inclusion
|
|
// of `ValidatedVariableAccess` nodes in `defaultTaintSanitizer`.
|
|
if (path.indexOf("..") != -1)
|
|
throw new Exception();
|
|
}
|
|
|
|
public void fileConstructorSanitizer() throws Exception {
|
|
// PathTraversalGuard
|
|
{
|
|
String source = (String) source();
|
|
File f1 = new File("safe/file.txt");
|
|
if (!source.contains("..")) {
|
|
File f2 = new File(f1, source);
|
|
sink(f2); // Safe
|
|
sink(source); // $ hasTaintFlow
|
|
} else {
|
|
File f3 = new File(f1, source);
|
|
sink(f3); // $ hasTaintFlow
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
File f1Tainted = (File) source();
|
|
if (!source.contains("..")) {
|
|
// `f2` is unsafe if `f1` is tainted
|
|
File f2 = new File(f1Tainted, source);
|
|
sink(f2); // $ hasTaintFlow
|
|
sink(source); // $ hasTaintFlow
|
|
} else {
|
|
File f3 = new File(f1Tainted, source);
|
|
sink(f3); // $ hasTaintFlow
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
File f1Null = null;
|
|
if (!source.contains("..")) {
|
|
// `f2` is unsafe if `f1` is null
|
|
File f2 = new File(f1Null, source);
|
|
sink(f2); // $ hasTaintFlow
|
|
sink(source); // $ hasTaintFlow
|
|
} else {
|
|
File f3 = new File(f1Null, source);
|
|
sink(f3); // $ hasTaintFlow
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
File f1 = new File("safe/file.txt");
|
|
if (source.indexOf("..") == -1) {
|
|
File f2 = new File(f1, source);
|
|
sink(f2); // Safe
|
|
sink(source); // $ hasTaintFlow
|
|
} else {
|
|
File f3 = new File(f1, source);
|
|
sink(f3); // $ hasTaintFlow
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
File f1 = new File("safe/file.txt");
|
|
if (source.indexOf("..") != -1) {
|
|
File f2 = new File(f1, source);
|
|
sink(f2); // $ hasTaintFlow
|
|
sink(source); // $ hasTaintFlow
|
|
} else {
|
|
File f3 = new File(f1, source);
|
|
sink(f3); // Safe
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
File f1 = new File("safe/file.txt");
|
|
if (source.lastIndexOf("..") == -1) {
|
|
File f2 = new File(f1, source);
|
|
sink(f2); // Safe
|
|
sink(source); // $ hasTaintFlow
|
|
} else {
|
|
File f3 = new File(f1, source);
|
|
sink(f3); // $ hasTaintFlow
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
// validation method
|
|
{
|
|
String source = (String) source();
|
|
File f1 = new File("safe/file.txt");
|
|
fileConstructorValidation(source);
|
|
File f2 = new File(f1, source);
|
|
sink(f2); // Safe
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
File f1 = new File("safe/file.txt");
|
|
|
|
if (source.contains("..")) {
|
|
throw new Exception();
|
|
} else {
|
|
File f2 = new File(f1, source);
|
|
sink(f2); // Safe
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
// PathNormalizeSanitizer
|
|
{
|
|
File source = (File) source();
|
|
String normalized = source.getCanonicalPath();
|
|
File f1 = new File("safe/file.txt");
|
|
File f2 = new File(f1, normalized);
|
|
sink(f2); // Safe
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
{
|
|
File source = (File) source();
|
|
String normalized = source.getCanonicalFile().toString();
|
|
File f1 = new File("safe/file.txt");
|
|
File f2 = new File(f1, normalized);
|
|
sink(f2); // Safe
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
String normalized = Paths.get(source).normalize().toString();
|
|
File f1 = new File("safe/file.txt");
|
|
File f2 = new File(f1, normalized);
|
|
sink(f2); // Safe
|
|
sink(source); // $ hasTaintFlow
|
|
sink(normalized); // $ hasTaintFlow
|
|
}
|
|
}
|
|
|
|
private void directoryCharsValidation(String path) throws Exception {
|
|
if (!path.matches("[0-9a-fA-F]{20,}")) {
|
|
throw new Exception();
|
|
}
|
|
}
|
|
|
|
public void directoryCharsSanitizer() throws Exception {
|
|
// DirectoryCharactersGuard
|
|
// Ensures that directory characters (/, \ and ..) cannot possibly be in the payload
|
|
// branch = true
|
|
{
|
|
String source = (String) source();
|
|
if (source.matches("[0-9a-fA-F]{20,}")) {
|
|
sink(source); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
if (source.matches("[0-9a-fA-F]*")) {
|
|
sink(source); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
if (source.matches("[0-9a-fA-F]+")) {
|
|
sink(source); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
if (source.matches("[0-9a-fA-F\\.]+")) {
|
|
sink(source); // $ hasTaintFlow
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
if (source.matches("[0-9a-fA-F/]+")) {
|
|
sink(source); // $ hasTaintFlow
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
if (source.matches("[0-9a-fA-F\\\\]+")) {
|
|
sink(source); // $ hasTaintFlow
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
// exclude '.', '/', '\'
|
|
if (source.matches("[^0-9./\\\\a-f]+")) {
|
|
sink(source); // Safe
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
// '/' is not excluded
|
|
if (source.matches("[^0-9.\\\\a-f]+")) {
|
|
sink(source); // $ hasTaintFlow
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
// branch = false
|
|
{
|
|
String source = (String) source();
|
|
if (source.matches(".*[\\./\\\\].*")) {
|
|
sink(source); // $ hasTaintFlow
|
|
} else {
|
|
sink(source); // Safe
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
if (source.matches(".+[\\./\\\\].+")) {
|
|
sink(source); // $ hasTaintFlow
|
|
} else {
|
|
sink(source); // Safe
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
// does not match whole string
|
|
if (source.matches("[\\./\\\\]+")) {
|
|
sink(source); // $ hasTaintFlow
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
// not a complete sanitizer since it doesn't protect against absolute path injection
|
|
if (source.matches(".+[\\.].+")) {
|
|
sink(source); // $ hasTaintFlow
|
|
} else {
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
// validation method
|
|
{
|
|
String source = (String) source();
|
|
directoryCharsValidation(source);
|
|
sink(source); // Safe
|
|
}
|
|
|
|
// ReplaceDirectoryCharactersSanitizer
|
|
// Removes ".." sequences and path separators from the payload
|
|
// single `replaceAll` call
|
|
{
|
|
String source = (String) source();
|
|
source = source.replaceAll("\\.\\.|[/\\\\]", "");
|
|
sink(source); // Safe
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
source = source.replaceAll("\\.|[/\\\\]", "-");
|
|
sink(source); // Safe
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
source = source.replaceAll("[.][.]|[/\\\\]", "_");
|
|
sink(source); // Safe
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
// test a not-accepted replacement character
|
|
source = source.replaceAll("[.][.]|[/\\\\]", "/");
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
source = source.replaceAll(".|[/\\\\]", "");
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
source = source.replaceAll("\\.|/|\\\\", "");
|
|
sink(source); // Safe
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
source = source.replaceAll("[\\./\\\\]", "");
|
|
sink(source); // Safe
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
source = source.replaceAll("[\\.\\\\]", "");
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
source = source.replaceAll("[^\\.\\\\/]", "");
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
// Bypassable with ".../...//"
|
|
source = source.replaceAll("\\.\\./", "");
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
// multiple `replaceAll` or `replace` calls
|
|
{
|
|
String source = (String) source();
|
|
source = source.replaceAll("\\.", "").replaceAll("/", "");
|
|
sink(source); // Safe
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
// test a not-accepted replacement character in each call
|
|
source = source.replaceAll("\\.", "/").replaceAll("/", ".");
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
// test a not-accepted replacement character in first call
|
|
source = source.replaceAll("\\.", "/").replaceAll("/", "-");
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
// test a not-accepted replacement character in second call
|
|
source = source.replaceAll("\\.", "_").replaceAll("/", ".");
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
source = source.replaceAll("\\.", "").replaceAll("/", "").replaceAll("\\\\", "");
|
|
sink(source); // Safe
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
// '/' or '\' are not replaced
|
|
source = source.replaceAll("\\.", "").replaceAll("\\.", "");
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
// '.' is not replaced
|
|
source = source.replaceAll("/", "").replaceAll("\\\\", "");
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
// Bypassable with ".....///"
|
|
source = source.replaceAll("\\.\\./", "").replaceAll("\\./", "");
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
source = source.replace(".", "").replace("/", "");
|
|
sink(source); // Safe
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
source = source.replace(".", "").replace("/", "").replace("\\", "");
|
|
sink(source); // Safe
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
// '/' or '\' are not replaced
|
|
source = source.replace(".", "").replace(".", "");
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
// '.' is not replaced
|
|
source = source.replace("/", "").replace("\\", "");
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
// Bypassable with ".....///"
|
|
source = source.replace("../", "").replace("./", "");
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
{
|
|
String source = (String) source();
|
|
// Bypassable with ".../...//"
|
|
source = source.replace("../", "");
|
|
sink(source); // $ hasTaintFlow
|
|
}
|
|
}
|
|
}
|