Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -64,7 +64,7 @@ object Deserialization {
// We can't instantiate jaz.Zer directly, so we instantiate and serialize jaz.Ter and then
// patch the class name.
val baos = ByteArrayOutputStream()
ObjectOutputStream(baos).writeObject(jaz.Ter(jaz.Ter.EXPRESSION_LANGUAGE_SANITIZER_ID))
ObjectOutputStream(baos).writeObject(jaz.Ter(jaz.Ter.DESERIALIZATION_SANITIZER_ID))
val serializedJazTerInstance = baos.toByteArray()
val posToPatch = serializedJazTerInstance.indexOf("jaz.Ter".toByteArray())
serializedJazTerInstance[posToPatch + "jaz.".length] = 'Z'.code.toByte()
Expand Down
35 changes: 7 additions & 28 deletions sanitizers/src/test/java/com/example/DisabledHooksTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
package com.example;

import com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Base64;
import org.junit.After;
import org.junit.Test;
Expand All @@ -31,15 +33,6 @@ public static void triggerReflectiveCallSanitizer() {
}
}

public static void triggerExpressionLanguageInjectionSanitizer() throws Throwable {
try {
Class.forName("jaz.Zer").getMethod("el").invoke(null);
} catch (InvocationTargetException e) {
throw e.getCause();
} catch (IllegalAccessException | ClassNotFoundException | NoSuchMethodException ignore) {
}
}

public static void triggerDeserializationSanitizer() {
byte[] data =
Base64.getDecoder().decode("rO0ABXNyAAdqYXouWmVyAAAAAAAAACoCAAFCAAlzYW5pdGl6ZXJ4cAEK");
Expand All @@ -65,11 +58,6 @@ public void enableDeserializationSanitizer() {
triggerDeserializationSanitizer();
}

@Test(expected = FuzzerSecurityIssueHigh.class)
public void enableExpressionLanguageInjectionSanitizer() throws Throwable {
triggerExpressionLanguageInjectionSanitizer();
}

@Test
public void disableReflectiveCallSanitizer() {
System.setProperty(
Expand All @@ -84,14 +72,6 @@ public void disableDeserializationSanitizer() {
triggerDeserializationSanitizer();
}

@Test
public void disableExpressionLanguageSanitizer() throws Throwable {
System.setProperty(
"jazzer.disabled_hooks",
"com.code_intelligence.jazzer.sanitizers.ExpressionLanguageInjection");
triggerExpressionLanguageInjectionSanitizer();
}

@Test(expected = FuzzerSecurityIssueHigh.class)
public void disableReflectiveCallAndEnableDeserialization() {
System.setProperty(
Expand All @@ -104,11 +84,10 @@ public void disableReflectiveCallAndEnableDeserialization() {
public void disableAllSanitizers() throws Throwable {
System.setProperty(
"jazzer.disabled_hooks",
"com.code_intelligence.jazzer.sanitizers.ReflectiveCall,"
+ "com.code_intelligence.jazzer.sanitizers.Deserialization,"
+ "com.code_intelligence.jazzer.sanitizers.ExpressionLanguageInjection");
"com.code_intelligence.jazzer.sanitizers.ReflectiveCall"
+ File.pathSeparatorChar
+ "com.code_intelligence.jazzer.sanitizers.Deserialization");
triggerReflectiveCallSanitizer();
triggerExpressionLanguageInjectionSanitizer();
triggerDeserializationSanitizer();
}
}
1 change: 0 additions & 1 deletion src/main/java/jaz/Ter.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ public class Ter implements java.io.Serializable {

public static final byte REFLECTIVE_CALL_SANITIZER_ID = 0;
public static final byte DESERIALIZATION_SANITIZER_ID = 1;
public static final byte EXPRESSION_LANGUAGE_SANITIZER_ID = 2;

private byte sanitizer = REFLECTIVE_CALL_SANITIZER_ID;

Expand Down
28 changes: 19 additions & 9 deletions src/main/java/jaz/Zer.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,18 @@

import com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh;
import com.code_intelligence.jazzer.api.Jazzer;
import java.io.*;
import java.util.*;
import java.io.Closeable;
import java.io.File;
import java.io.Flushable;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.Callable;
import java.util.function.Function;

Expand Down Expand Up @@ -61,7 +71,6 @@ public class Zer
// serialized size is 41 bytes
private static final byte REFLECTIVE_CALL_SANITIZER_ID = 0;
private static final byte DESERIALIZATION_SANITIZER_ID = 1;
private static final byte EXPRESSION_LANGUAGE_SANITIZER_ID = 2;

// A byte representing the relevant sanitizer for a given jaz.Zer instance. It is used to check
// whether the corresponding sanitizer is disabled and jaz.Zer will not report a finding in this
Expand Down Expand Up @@ -91,11 +100,13 @@ public Zer(byte sanitizer) {
reportFindingIfEnabled();
}

// A special static method that is called by the expression language injection sanitizer. We
// A special static method that is guided to by the expression language injection sanitizer. We
// choose a parameterless method to keep the string that the sanitizer guides the fuzzer to
// generate within the 64-byte boundary required by the corresponding guiding methods.
// A RCE finding is only reported if the ReflectiveCall sanitizer is active to give users a way to
// silence it.
public static void el() {
if (isSanitizerEnabled(EXPRESSION_LANGUAGE_SANITIZER_ID)) {
if (isSanitizerEnabled(REFLECTIVE_CALL_SANITIZER_ID)) {
reportFinding();
}
}
Expand All @@ -116,6 +127,7 @@ private static void reportFinding() {
}

private static boolean isSanitizerEnabled(byte sanitizerId) {
// FIXME: This does not take into account disabled hooks set via CLI args or env.
String allDisabledHooks = System.getProperty("jazzer.disabled_hooks");
if (allDisabledHooks == null || allDisabledHooks.equals("")) {
return true;
Expand All @@ -126,13 +138,11 @@ private static boolean isSanitizerEnabled(byte sanitizerId) {
case DESERIALIZATION_SANITIZER_ID:
sanitizer = "com.code_intelligence.jazzer.sanitizers.Deserialization";
break;
case EXPRESSION_LANGUAGE_SANITIZER_ID:
sanitizer = "com.code_intelligence.jazzer.sanitizers.ExpressionLanguageInjection";
break;
default:
sanitizer = "com.code_intelligence.jazzer.sanitizers.ReflectiveCall";
}
return Arrays.stream(allDisabledHooks.split(",")).noneMatch(sanitizer::equals);
return Arrays.stream(allDisabledHooks.split(String.valueOf(File.pathSeparatorChar)))
.noneMatch(sanitizer::equals);
}

// Getter/Setter
Expand Down