aboutsummaryrefslogtreecommitdiff
path: root/sanitizers
diff options
context:
space:
mode:
authorNorbert Schneider <norbert.schneider@code-intelligence.com>2022-03-01 12:46:52 +0100
committerNorbert Schneider <mail@bertschneider.de>2022-03-03 15:07:33 +0100
commitb2e8a9dca69227f2952ec80020f436789efae887 (patch)
tree0a0c04f767e5fb57c871dc90d66f6459d828ce7d /sanitizers
parente966b316e9c44817cad19a5bd59f42b790e33f86 (diff)
downloadjazzer-api-b2e8a9dca69227f2952ec80020f436789efae887.tar.gz
Hook ClassLoader methods
Hook all Class.forName and ClassLoader.loadClass methods. Some are protected or even final but could be used by subclasses.
Diffstat (limited to 'sanitizers')
-rw-r--r--sanitizers/src/main/java/com/code_intelligence/jazzer/sanitizers/ReflectiveCall.kt24
-rw-r--r--sanitizers/src/test/java/com/example/BUILD.bazel12
-rw-r--r--sanitizers/src/test/java/com/example/ClassLoaderLoadClass.java30
-rw-r--r--sanitizers/src/test/java/com/example/ReflectiveCall.java6
4 files changed, 64 insertions, 8 deletions
diff --git a/sanitizers/src/main/java/com/code_intelligence/jazzer/sanitizers/ReflectiveCall.kt b/sanitizers/src/main/java/com/code_intelligence/jazzer/sanitizers/ReflectiveCall.kt
index 3dfd3ca1..7072cc7d 100644
--- a/sanitizers/src/main/java/com/code_intelligence/jazzer/sanitizers/ReflectiveCall.kt
+++ b/sanitizers/src/main/java/com/code_intelligence/jazzer/sanitizers/ReflectiveCall.kt
@@ -17,18 +17,36 @@ package com.code_intelligence.jazzer.sanitizers
import com.code_intelligence.jazzer.api.HookType
import com.code_intelligence.jazzer.api.Jazzer
import com.code_intelligence.jazzer.api.MethodHook
+import com.code_intelligence.jazzer.api.MethodHooks
import java.lang.invoke.MethodHandle
/**
- * Detects unsafe reflective calls that lead to attacker-controlled method calls.
+ * Detects unsafe calls that lead to attacker-controlled class loading.
+ *
+ * Guide the fuzzer to load honeypot class via [Class.forName] or [ClassLoader.loadClass].
*/
@Suppress("unused_parameter", "unused")
object ReflectiveCall {
- @MethodHook(type = HookType.BEFORE, targetClassName = "java.lang.Class", targetMethod = "forName")
+ @MethodHooks(
+ MethodHook(type = HookType.BEFORE, targetClassName = "java.lang.Class", targetMethod = "forName", targetMethodDescriptor = "(Ljava/lang/String;)Ljava/lang/Class;"),
+ MethodHook(type = HookType.BEFORE, targetClassName = "java.lang.Class", targetMethod = "forName", targetMethodDescriptor = "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
+ MethodHook(type = HookType.BEFORE, targetClassName = "java.lang.ClassLoader", targetMethod = "loadClass", targetMethodDescriptor = "(Ljava/lang/String;)Ljava/lang/Class;"),
+ MethodHook(type = HookType.BEFORE, targetClassName = "java.lang.ClassLoader", targetMethod = "loadClass", targetMethodDescriptor = "(Ljava/lang/String;Z)Ljava/lang/Class;"),
+ )
@JvmStatic
- fun classForNameHook(method: MethodHandle?, alwaysNull: Any?, args: Array<Any?>, hookId: Int) {
+ fun loadClassHook(method: MethodHandle?, alwaysNull: Any?, args: Array<Any?>, hookId: Int) {
val className = args[0] as? String ?: return
Jazzer.guideTowardsEquality(className, HONEYPOT_CLASS_NAME, hookId)
}
+
+ @MethodHooks(
+ MethodHook(type = HookType.BEFORE, targetClassName = "java.lang.Class", targetMethod = "forName", targetMethodDescriptor = "(Ljava/lang/Module;Ljava/lang/String;)Ljava/lang/Class;"),
+ MethodHook(type = HookType.BEFORE, targetClassName = "java.lang.ClassLoader", targetMethod = "loadClass", targetMethodDescriptor = "(Ljava/lang/Module;Ljava/lang/String;)Ljava/lang/Class;"),
+ )
+ @JvmStatic
+ fun loadClassWithModuleHook(method: MethodHandle?, alwaysNull: Any?, args: Array<Any?>, hookId: Int) {
+ val className = args[1] as? String ?: return
+ Jazzer.guideTowardsEquality(className, HONEYPOT_CLASS_NAME, hookId)
+ }
}
diff --git a/sanitizers/src/test/java/com/example/BUILD.bazel b/sanitizers/src/test/java/com/example/BUILD.bazel
index 7a6064fc..5279fe2e 100644
--- a/sanitizers/src/test/java/com/example/BUILD.bazel
+++ b/sanitizers/src/test/java/com/example/BUILD.bazel
@@ -78,6 +78,16 @@ java_fuzz_target_test(
java_fuzz_target_test(
name = "RegexCanonEqInjection",
- srcs = ["RegexCanonEqInjection.java"],
+ srcs = [
+ "RegexCanonEqInjection.java",
+ ],
target_class = "com.example.RegexCanonEqInjection",
)
+
+java_fuzz_target_test(
+ name = "ClassLoaderLoadClass",
+ srcs = [
+ "ClassLoaderLoadClass.java",
+ ],
+ target_class = "com.example.ClassLoaderLoadClass",
+)
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/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) {
}
}
}