aboutsummaryrefslogtreecommitdiff
path: root/sanitizers/src/test/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'sanitizers/src/test/java/com')
-rw-r--r--sanitizers/src/test/java/com/example/BUILD.bazel108
-rw-r--r--sanitizers/src/test/java/com/example/ClassLoaderLoadClass.java30
-rw-r--r--sanitizers/src/test/java/com/example/LdapDnInjection.java39
-rw-r--r--sanitizers/src/test/java/com/example/LdapSearchInjection.java39
-rw-r--r--sanitizers/src/test/java/com/example/LibraryLoad.java29
-rw-r--r--sanitizers/src/test/java/com/example/OsCommandInjectionProcessBuilder.java35
-rw-r--r--sanitizers/src/test/java/com/example/OsCommandInjectionRuntimeExec.java35
-rw-r--r--sanitizers/src/test/java/com/example/ReflectiveCall.java6
-rw-r--r--sanitizers/src/test/java/com/example/RegexCanonEqInjection.java41
-rw-r--r--sanitizers/src/test/java/com/example/RegexInsecureQuoteInjection.java29
-rw-r--r--sanitizers/src/test/java/com/example/RegexRoadblocks.java89
-rw-r--r--sanitizers/src/test/java/com/example/SqlInjection.java41
-rw-r--r--sanitizers/src/test/java/com/example/ldap/MockInitialContextFactory.java26
-rw-r--r--sanitizers/src/test/java/com/example/ldap/MockLdapContext.java316
14 files changed, 859 insertions, 4 deletions
diff --git a/sanitizers/src/test/java/com/example/BUILD.bazel b/sanitizers/src/test/java/com/example/BUILD.bazel
index d148545a..5d2e1ca5 100644
--- a/sanitizers/src/test/java/com/example/BUILD.bazel
+++ b/sanitizers/src/test/java/com/example/BUILD.bazel
@@ -1,10 +1,12 @@
load("//bazel:fuzz_target.bzl", "java_fuzz_target_test")
+load("//bazel:compat.bzl", "SKIP_ON_MACOS")
java_fuzz_target_test(
name = "ObjectInputStreamDeserialization",
srcs = [
"ObjectInputStreamDeserialization.java",
],
+ expected_findings = ["java.lang.ExceptionInInitializerError"],
target_class = "com.example.ObjectInputStreamDeserialization",
)
@@ -13,10 +15,22 @@ java_fuzz_target_test(
srcs = [
"ReflectiveCall.java",
],
+ expected_findings = ["java.lang.ExceptionInInitializerError"],
target_class = "com.example.ReflectiveCall",
)
java_fuzz_target_test(
+ name = "LibraryLoad",
+ srcs = [
+ "LibraryLoad.java",
+ ],
+ target_class = "com.example.LibraryLoad",
+ # loading of native libraries is very slow on macos,
+ # especially using Java 17
+ target_compatible_with = SKIP_ON_MACOS,
+)
+
+java_fuzz_target_test(
name = "ExpressionLanguageInjection",
srcs = [
"ExpressionLanguageInjection.java",
@@ -27,6 +41,100 @@ java_fuzz_target_test(
"@maven//:javax_el_javax_el_api",
"@maven//:javax_validation_validation_api",
"@maven//:javax_xml_bind_jaxb_api",
+ "@maven//:org_glassfish_javax_el",
"@maven//:org_hibernate_hibernate_validator",
],
)
+
+java_fuzz_target_test(
+ name = "OsCommandInjectionProcessBuilder",
+ srcs = [
+ "OsCommandInjectionProcessBuilder.java",
+ ],
+ target_class = "com.example.OsCommandInjectionProcessBuilder",
+)
+
+java_fuzz_target_test(
+ name = "OsCommandInjectionRuntimeExec",
+ srcs = [
+ "OsCommandInjectionRuntimeExec.java",
+ ],
+ target_class = "com.example.OsCommandInjectionRuntimeExec",
+)
+
+java_fuzz_target_test(
+ name = "LdapSearchInjection",
+ srcs = [
+ "LdapSearchInjection.java",
+ "ldap/MockInitialContextFactory.java",
+ "ldap/MockLdapContext.java",
+ ],
+ expected_findings = ["javax.naming.directory.InvalidSearchFilterException"],
+ target_class = "com.example.LdapSearchInjection",
+ deps = [
+ "@maven//:com_unboundid_unboundid_ldapsdk",
+ ],
+)
+
+java_fuzz_target_test(
+ name = "LdapDnInjection",
+ srcs = [
+ "LdapDnInjection.java",
+ "ldap/MockInitialContextFactory.java",
+ "ldap/MockLdapContext.java",
+ ],
+ expected_findings = ["javax.naming.NamingException"],
+ target_class = "com.example.LdapDnInjection",
+ deps = [
+ "@maven//:com_unboundid_unboundid_ldapsdk",
+ ],
+)
+
+java_fuzz_target_test(
+ name = "RegexInsecureQuoteInjection",
+ srcs = ["RegexInsecureQuoteInjection.java"],
+ target_class = "com.example.RegexInsecureQuoteInjection",
+)
+
+java_fuzz_target_test(
+ name = "RegexCanonEqInjection",
+ srcs = [
+ "RegexCanonEqInjection.java",
+ ],
+ target_class = "com.example.RegexCanonEqInjection",
+)
+
+java_fuzz_target_test(
+ name = "ClassLoaderLoadClass",
+ srcs = [
+ "ClassLoaderLoadClass.java",
+ ],
+ expected_findings = ["java.lang.ExceptionInInitializerError"],
+ target_class = "com.example.ClassLoaderLoadClass",
+)
+
+java_fuzz_target_test(
+ name = "RegexRoadblocks",
+ srcs = ["RegexRoadblocks.java"],
+ fuzzer_args = [
+ # Limit the number of runs to verify that the regex roadblocks are
+ # cleared quickly.
+ "-runs=22000",
+ ],
+ target_class = "com.example.RegexRoadblocks",
+)
+
+java_fuzz_target_test(
+ name = "SqlInjection",
+ srcs = [
+ "SqlInjection.java",
+ ],
+ expected_findings = [
+ "com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh",
+ "org.h2.jdbc.JdbcSQLSyntaxErrorException",
+ ],
+ target_class = "com.example.SqlInjection",
+ deps = [
+ "@maven//:com_h2database_h2",
+ ],
+)
diff --git a/sanitizers/src/test/java/com/example/ClassLoaderLoadClass.java b/sanitizers/src/test/java/com/example/ClassLoaderLoadClass.java
new file mode 100644
index 00000000..c3fa47ac
--- /dev/null
+++ b/sanitizers/src/test/java/com/example/ClassLoaderLoadClass.java
@@ -0,0 +1,30 @@
+// Copyright 2021 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.example;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import java.lang.reflect.InvocationTargetException;
+
+public class ClassLoaderLoadClass {
+ public static void fuzzerTestOneInput(FuzzedDataProvider data) throws InterruptedException {
+ String input = data.consumeRemainingAsAsciiString();
+ try {
+ // create an instance to trigger class initialization
+ ClassLoaderLoadClass.class.getClassLoader().loadClass(input).getConstructor().newInstance();
+ } catch (ClassNotFoundException | InvocationTargetException | InstantiationException
+ | IllegalAccessException | NoSuchMethodException ignored) {
+ }
+ }
+}
diff --git a/sanitizers/src/test/java/com/example/LdapDnInjection.java b/sanitizers/src/test/java/com/example/LdapDnInjection.java
new file mode 100644
index 00000000..911db1dc
--- /dev/null
+++ b/sanitizers/src/test/java/com/example/LdapDnInjection.java
@@ -0,0 +1,39 @@
+// Copyright 2021 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.example;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import java.util.Hashtable;
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.directory.InitialDirContext;
+import javax.naming.directory.SearchControls;
+
+public class LdapDnInjection {
+ private static InitialDirContext ctx;
+
+ public static void fuzzerInitialize() throws NamingException {
+ Hashtable<String, String> env = new Hashtable<>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, "com.example.ldap.MockInitialContextFactory");
+ ctx = new InitialDirContext(env);
+ }
+
+ public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) throws Exception {
+ // Externally provided DN input needs to be escaped properly
+ String ou = fuzzedDataProvider.consumeRemainingAsString();
+ String base = "ou=" + ou + ",dc=example,dc=com";
+ ctx.search(base, "(&(uid=foo)(cn=bar))", new SearchControls());
+ }
+}
diff --git a/sanitizers/src/test/java/com/example/LdapSearchInjection.java b/sanitizers/src/test/java/com/example/LdapSearchInjection.java
new file mode 100644
index 00000000..b3dfee74
--- /dev/null
+++ b/sanitizers/src/test/java/com/example/LdapSearchInjection.java
@@ -0,0 +1,39 @@
+// Copyright 2021 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.example;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import java.util.Hashtable;
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.directory.SearchControls;
+import javax.naming.ldap.InitialLdapContext;
+
+public class LdapSearchInjection {
+ private static InitialLdapContext ctx;
+
+ public static void fuzzerInitialize() throws NamingException {
+ Hashtable<String, String> env = new Hashtable<>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, "com.example.ldap.MockInitialContextFactory");
+ ctx = new InitialLdapContext(env, null);
+ }
+
+ public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) throws Exception {
+ // Externally provided LDAP query input needs to be escaped properly
+ String username = fuzzedDataProvider.consumeRemainingAsAsciiString();
+ String filter = "(&(uid=" + username + ")(ou=security))";
+ ctx.search("dc=example,dc=com", filter, new SearchControls());
+ }
+}
diff --git a/sanitizers/src/test/java/com/example/LibraryLoad.java b/sanitizers/src/test/java/com/example/LibraryLoad.java
new file mode 100644
index 00000000..81411767
--- /dev/null
+++ b/sanitizers/src/test/java/com/example/LibraryLoad.java
@@ -0,0 +1,29 @@
+// Copyright 2021 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.example;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+
+public class LibraryLoad {
+ public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+ String input = data.consumeRemainingAsAsciiString();
+
+ try {
+ System.loadLibrary(input);
+ } catch (SecurityException | UnsatisfiedLinkError | NullPointerException
+ | IllegalArgumentException ignored) {
+ }
+ }
+}
diff --git a/sanitizers/src/test/java/com/example/OsCommandInjectionProcessBuilder.java b/sanitizers/src/test/java/com/example/OsCommandInjectionProcessBuilder.java
new file mode 100644
index 00000000..f5d52782
--- /dev/null
+++ b/sanitizers/src/test/java/com/example/OsCommandInjectionProcessBuilder.java
@@ -0,0 +1,35 @@
+// Copyright 2021 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.example;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import java.util.concurrent.TimeUnit;
+
+public class OsCommandInjectionProcessBuilder {
+ public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+ String input = data.consumeRemainingAsAsciiString();
+ try {
+ ProcessBuilder processBuilder = new ProcessBuilder(input);
+ processBuilder.environment().clear();
+ Process process = processBuilder.start();
+ // This should be way faster, but we have to wait until the call is done
+ if (!process.waitFor(10, TimeUnit.MILLISECONDS)) {
+ process.destroyForcibly();
+ }
+ } catch (Exception ignored) {
+ // Ignore execution and setup exceptions
+ }
+ }
+}
diff --git a/sanitizers/src/test/java/com/example/OsCommandInjectionRuntimeExec.java b/sanitizers/src/test/java/com/example/OsCommandInjectionRuntimeExec.java
new file mode 100644
index 00000000..c620a751
--- /dev/null
+++ b/sanitizers/src/test/java/com/example/OsCommandInjectionRuntimeExec.java
@@ -0,0 +1,35 @@
+// Copyright 2021 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.example;
+
+import static java.lang.Runtime.getRuntime;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import java.util.concurrent.TimeUnit;
+
+public class OsCommandInjectionRuntimeExec {
+ public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+ String input = data.consumeRemainingAsAsciiString();
+ try {
+ Process process = getRuntime().exec(input, new String[] {});
+ // This should be way faster, but we have to wait until the call is done
+ if (!process.waitFor(10, TimeUnit.MILLISECONDS)) {
+ process.destroyForcibly();
+ }
+ } catch (Exception ignored) {
+ // Ignore execution and setup exceptions
+ }
+ }
+}
diff --git a/sanitizers/src/test/java/com/example/ReflectiveCall.java b/sanitizers/src/test/java/com/example/ReflectiveCall.java
index 7f85e486..e6b62b45 100644
--- a/sanitizers/src/test/java/com/example/ReflectiveCall.java
+++ b/sanitizers/src/test/java/com/example/ReflectiveCall.java
@@ -15,7 +15,6 @@
package com.example;
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
-import java.lang.reflect.InvocationTargetException;
public class ReflectiveCall {
public static void fuzzerTestOneInput(FuzzedDataProvider data) {
@@ -23,9 +22,8 @@ public class ReflectiveCall {
if (input.startsWith("@")) {
String className = input.substring(1);
try {
- Class.forName(className).getConstructor().newInstance();
- } catch (InstantiationException | IllegalAccessException | InvocationTargetException
- | NoSuchMethodException | ClassNotFoundException ignored) {
+ Class.forName(className);
+ } catch (ClassNotFoundException ignored) {
}
}
}
diff --git a/sanitizers/src/test/java/com/example/RegexCanonEqInjection.java b/sanitizers/src/test/java/com/example/RegexCanonEqInjection.java
new file mode 100644
index 00000000..e2d0b722
--- /dev/null
+++ b/sanitizers/src/test/java/com/example/RegexCanonEqInjection.java
@@ -0,0 +1,41 @@
+// Copyright 2022 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.example;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+public class RegexCanonEqInjection {
+ public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+ String input = data.consumeRemainingAsString();
+ try {
+ Pattern.compile(Pattern.quote(input), Pattern.CANON_EQ);
+ } catch (PatternSyntaxException ignored) {
+ } catch (IllegalArgumentException ignored) {
+ // "[媼" generates an IllegalArgumentException but only on Windows using
+ // Java 8. We ignore this for now.
+ //
+ // java.lang.IllegalArgumentException
+ // at java.lang.AbstractStringBuilder.appendCodePoint(AbstractStringBuilder.java:800)
+ // at java.lang.StringBuilder.appendCodePoint(StringBuilder.java:240)
+ // at java.util.regex.Pattern.normalizeCharClass(Pattern.java:1430)
+ // at java.util.regex.Pattern.normalize(Pattern.java:1396)
+ // at java.util.regex.Pattern.compile(Pattern.java:1665)
+ // at java.util.regex.Pattern.<init>(Pattern.java:1352)
+ // at java.util.regex.Pattern.compile(Pattern.java:1054)
+ }
+ }
+}
diff --git a/sanitizers/src/test/java/com/example/RegexInsecureQuoteInjection.java b/sanitizers/src/test/java/com/example/RegexInsecureQuoteInjection.java
new file mode 100644
index 00000000..a548cfb2
--- /dev/null
+++ b/sanitizers/src/test/java/com/example/RegexInsecureQuoteInjection.java
@@ -0,0 +1,29 @@
+// Copyright 2022 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.example;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+public class RegexInsecureQuoteInjection {
+ public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+ String input = data.consumeRemainingAsString();
+ try {
+ Pattern.matches("\\Q" + input + "\\E", "foobar");
+ } catch (PatternSyntaxException ignored) {
+ }
+ }
+}
diff --git a/sanitizers/src/test/java/com/example/RegexRoadblocks.java b/sanitizers/src/test/java/com/example/RegexRoadblocks.java
new file mode 100644
index 00000000..21986e3d
--- /dev/null
+++ b/sanitizers/src/test/java/com/example/RegexRoadblocks.java
@@ -0,0 +1,89 @@
+// Copyright 2022 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.example;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow;
+import java.util.regex.Pattern;
+
+public class RegexRoadblocks {
+ // We accept arbitrary suffixes but not prefixes for the following reasons:
+ // 1. The fuzzer will take much longer to match the exact length of the input than to satisfy the
+ // compare checks, which is what we really want to test.
+ // 2. Accepting arbitrary prefixes could lead to tests passing purely due to ToC entries being
+ // emitted in arbitrary positions, but we want to ensure that compares are correctly reported
+ // including position hints.
+ private static final Pattern LITERAL = Pattern.compile("foobarbaz.*");
+ private static final Pattern QUOTED_LITERAL = Pattern.compile(Pattern.quote("jazzer_is_cool.*"));
+ private static final Pattern CASE_INSENSITIVE_LITERAL =
+ Pattern.compile("JaZzER!.*", Pattern.CASE_INSENSITIVE);
+ private static final Pattern GROUP = Pattern.compile("(always).*");
+ private static final Pattern ALTERNATIVE = Pattern.compile("(to_be|not_to_be).*");
+ private static final Pattern SINGLE_LATIN1_CHAR_PROPERTY = Pattern.compile("[€].*");
+ private static final Pattern MULTIPLE_LATIN1_CHAR_PROPERTY = Pattern.compile("[ẞÄ].*");
+ private static final Pattern RANGE_LATIN1_CHAR_PROPERTY = Pattern.compile("[¢-¥].*");
+
+ private static int run = 0;
+
+ private static boolean matchedLiteral = false;
+ private static boolean matchedQuotedLiteral = false;
+ private static boolean matchedCaseInsensitiveLiteral = false;
+ private static boolean matchedGroup = false;
+ private static boolean matchedAlternative = false;
+ private static boolean matchedSingleLatin1CharProperty = false;
+ private static boolean matchedMultipleLatin1CharProperty = false;
+ private static boolean matchedRangeLatin1CharProperty = false;
+
+ public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+ run++;
+ String input = data.consumeRemainingAsString();
+
+ if (!matchedLiteral && LITERAL.matcher(input).matches()) {
+ System.out.println("Cleared LITERAL");
+ matchedLiteral = true;
+ } else if (!matchedQuotedLiteral && QUOTED_LITERAL.matcher(input).matches()) {
+ System.out.println("Cleared QUOTED_LITERAL");
+ matchedQuotedLiteral = true;
+ } else if (!matchedCaseInsensitiveLiteral
+ && CASE_INSENSITIVE_LITERAL.matcher(input).matches()) {
+ System.out.println("Cleared CASE_INSENSITIVE_LITERAL");
+ matchedCaseInsensitiveLiteral = true;
+ } else if (!matchedGroup && GROUP.matcher(input).matches()) {
+ System.out.println("Cleared GROUP");
+ matchedGroup = true;
+ } else if (!matchedAlternative && ALTERNATIVE.matcher(input).matches()) {
+ System.out.println("Cleared ALTERNATIVE");
+ matchedAlternative = true;
+ } else if (!matchedSingleLatin1CharProperty
+ && SINGLE_LATIN1_CHAR_PROPERTY.matcher(input).matches()) {
+ System.out.println("Cleared SINGLE_LATIN1_CHAR_PROPERTY");
+ matchedSingleLatin1CharProperty = true;
+ } else if (!matchedMultipleLatin1CharProperty
+ && MULTIPLE_LATIN1_CHAR_PROPERTY.matcher(input).matches()) {
+ System.out.println("Cleared MULTIPLE_LATIN1_CHAR_PROPERTY");
+ matchedMultipleLatin1CharProperty = true;
+ } else if (!matchedRangeLatin1CharProperty
+ && RANGE_LATIN1_CHAR_PROPERTY.matcher(input).matches()) {
+ System.out.println("Cleared RANGE_LATIN1_CHAR_PROPERTY");
+ matchedRangeLatin1CharProperty = true;
+ }
+
+ if (matchedLiteral && matchedQuotedLiteral && matchedCaseInsensitiveLiteral && matchedGroup
+ && matchedAlternative && matchedSingleLatin1CharProperty
+ && matchedMultipleLatin1CharProperty && matchedRangeLatin1CharProperty) {
+ throw new FuzzerSecurityIssueLow("Fuzzer matched all regexes in " + run + " runs");
+ }
+ }
+}
diff --git a/sanitizers/src/test/java/com/example/SqlInjection.java b/sanitizers/src/test/java/com/example/SqlInjection.java
new file mode 100644
index 00000000..8a16b5c8
--- /dev/null
+++ b/sanitizers/src/test/java/com/example/SqlInjection.java
@@ -0,0 +1,41 @@
+// Copyright 2022 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.example;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import java.sql.Connection;
+import java.sql.SQLException;
+import org.h2.jdbcx.JdbcDataSource;
+
+public class SqlInjection {
+ static Connection conn = null;
+
+ public static void fuzzerInitialize() throws Exception {
+ JdbcDataSource ds = new JdbcDataSource();
+ ds.setURL("jdbc:h2:./test.db");
+ conn = ds.getConnection();
+ conn.createStatement().execute(
+ "CREATE TABLE IF NOT EXISTS pet (id IDENTITY PRIMARY KEY, name VARCHAR(50))");
+ }
+
+ static void insecureInsertUser(String userName) throws SQLException {
+ // Never use String.format instead of java.sql.Connection.prepareStatement ...
+ conn.createStatement().execute(String.format("INSERT INTO pet (name) VALUES ('%s')", userName));
+ }
+
+ public static void fuzzerTestOneInput(FuzzedDataProvider data) throws Exception {
+ insecureInsertUser(data.consumeRemainingAsString());
+ }
+}
diff --git a/sanitizers/src/test/java/com/example/ldap/MockInitialContextFactory.java b/sanitizers/src/test/java/com/example/ldap/MockInitialContextFactory.java
new file mode 100644
index 00000000..b674f5c5
--- /dev/null
+++ b/sanitizers/src/test/java/com/example/ldap/MockInitialContextFactory.java
@@ -0,0 +1,26 @@
+// Copyright 2021 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.example.ldap;
+
+import java.util.Hashtable;
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+
+public class MockInitialContextFactory implements InitialContextFactory {
+ public Context getInitialContext(Hashtable environment) {
+ return new MockLdapContext();
+ }
+}
diff --git a/sanitizers/src/test/java/com/example/ldap/MockLdapContext.java b/sanitizers/src/test/java/com/example/ldap/MockLdapContext.java
new file mode 100644
index 00000000..a51fadcd
--- /dev/null
+++ b/sanitizers/src/test/java/com/example/ldap/MockLdapContext.java
@@ -0,0 +1,316 @@
+// Copyright 2021 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.example.ldap;
+
+import com.unboundid.ldap.sdk.DN;
+import com.unboundid.ldap.sdk.Filter;
+import com.unboundid.ldap.sdk.LDAPException;
+import java.util.Hashtable;
+import javax.naming.*;
+import javax.naming.directory.*;
+import javax.naming.ldap.*;
+
+/**
+ * Mock LdapContex implementation to test LdapInjection hook configuration.
+ *
+ * Only {@code com.example.ldap.MockLdapContext#search(java.lang.String, java.lang.String,
+ * javax.naming.directory.SearchControls)} is implemented to validate DN and filer query.
+ */
+public class MockLdapContext implements LdapContext {
+ @Override
+ public ExtendedResponse extendedOperation(ExtendedRequest request) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public LdapContext newInstance(Control[] requestControls) throws NamingException {
+ return this;
+ }
+
+ @Override
+ public void reconnect(Control[] connCtls) throws NamingException {}
+
+ @Override
+ public Control[] getConnectControls() throws NamingException {
+ return new Control[0];
+ }
+
+ @Override
+ public void setRequestControls(Control[] requestControls) throws NamingException {}
+
+ @Override
+ public Control[] getRequestControls() throws NamingException {
+ return new Control[0];
+ }
+
+ @Override
+ public Control[] getResponseControls() throws NamingException {
+ return new Control[0];
+ }
+
+ @Override
+ public Attributes getAttributes(Name name) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Attributes getAttributes(String name) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Attributes getAttributes(Name name, String[] attrIds) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Attributes getAttributes(String name, String[] attrIds) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public void modifyAttributes(Name name, int mod_op, Attributes attrs) throws NamingException {}
+
+ @Override
+ public void modifyAttributes(String name, int mod_op, Attributes attrs) throws NamingException {}
+
+ @Override
+ public void modifyAttributes(Name name, ModificationItem[] mods) throws NamingException {}
+
+ @Override
+ public void modifyAttributes(String name, ModificationItem[] mods) throws NamingException {}
+
+ @Override
+ public void bind(Name name, Object obj, Attributes attrs) throws NamingException {}
+
+ @Override
+ public void bind(String name, Object obj, Attributes attrs) throws NamingException {}
+
+ @Override
+ public void rebind(Name name, Object obj, Attributes attrs) throws NamingException {}
+
+ @Override
+ public void rebind(String name, Object obj, Attributes attrs) throws NamingException {}
+
+ @Override
+ public DirContext createSubcontext(Name name, Attributes attrs) throws NamingException {
+ return this;
+ }
+
+ @Override
+ public DirContext createSubcontext(String name, Attributes attrs) throws NamingException {
+ return this;
+ }
+
+ @Override
+ public DirContext getSchema(Name name) throws NamingException {
+ return this;
+ }
+
+ @Override
+ public DirContext getSchema(String name) throws NamingException {
+ return this;
+ }
+
+ @Override
+ public DirContext getSchemaClassDefinition(Name name) throws NamingException {
+ return this;
+ }
+
+ @Override
+ public DirContext getSchemaClassDefinition(String name) throws NamingException {
+ return this;
+ }
+
+ @Override
+ public NamingEnumeration<SearchResult> search(Name name, Attributes matchingAttributes,
+ String[] attributesToReturn) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<SearchResult> search(String name, Attributes matchingAttributes,
+ String[] attributesToReturn) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<SearchResult> search(Name name, Attributes matchingAttributes)
+ throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<SearchResult> search(String name, Attributes matchingAttributes)
+ throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
+ throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<SearchResult> search(String name, String filter, SearchControls cons)
+ throws NamingException {
+ // Use UnboundID LDAP to validate DN and filter
+ if (!DN.isValidDN(name)) {
+ throw new NamingException("Invalid DN " + name);
+ }
+ try {
+ Filter.create(filter);
+ } catch (LDAPException e) {
+ throw new InvalidSearchFilterException("Invalid search filter " + filter);
+ }
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<SearchResult> search(Name name, String filterExpr, Object[] filterArgs,
+ SearchControls cons) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<SearchResult> search(String name, String filterExpr, Object[] filterArgs,
+ SearchControls cons) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Object lookup(Name name) throws NamingException {
+ return this;
+ }
+
+ @Override
+ public Object lookup(String name) throws NamingException {
+ return this;
+ }
+
+ @Override
+ public void bind(Name name, Object obj) throws NamingException {}
+
+ @Override
+ public void bind(String name, Object obj) throws NamingException {}
+
+ @Override
+ public void rebind(Name name, Object obj) throws NamingException {}
+
+ @Override
+ public void rebind(String name, Object obj) throws NamingException {}
+
+ @Override
+ public void unbind(Name name) throws NamingException {}
+
+ @Override
+ public void unbind(String name) throws NamingException {}
+
+ @Override
+ public void rename(Name oldName, Name newName) throws NamingException {}
+
+ @Override
+ public void rename(String oldName, String newName) throws NamingException {}
+
+ @Override
+ public NamingEnumeration<NameClassPair> list(Name name) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<NameClassPair> list(String name) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<Binding> listBindings(Name name) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<Binding> listBindings(String name) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public void destroySubcontext(Name name) throws NamingException {}
+
+ @Override
+ public void destroySubcontext(String name) throws NamingException {}
+
+ @Override
+ public Context createSubcontext(Name name) throws NamingException {
+ return this;
+ }
+
+ @Override
+ public Context createSubcontext(String name) throws NamingException {
+ return this;
+ }
+
+ @Override
+ public Object lookupLink(Name name) throws NamingException {
+ return this;
+ }
+
+ @Override
+ public Object lookupLink(String name) throws NamingException {
+ return this;
+ }
+
+ @Override
+ public NameParser getNameParser(Name name) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NameParser getNameParser(String name) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Name composeName(Name name, Name prefix) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public String composeName(String name, String prefix) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Object addToEnvironment(String propName, Object propVal) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Object removeFromEnvironment(String propName) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Hashtable<?, ?> getEnvironment() throws NamingException {
+ return null;
+ }
+
+ @Override
+ public void close() throws NamingException {}
+
+ @Override
+ public String getNameInNamespace() throws NamingException {
+ return null;
+ }
+}