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
1 change: 1 addition & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ TEST_MAVEN_ARTIFACTS = [
"jakarta.validation:jakarta.validation-api:3.0.2",
"javax.persistence:javax.persistence-api:2.2",
"junit:junit:4.13.2",
"ognl:ognl:3.3.0",
"org.apache.commons:commons-jexl:2.1.1",
"org.assertj:assertj-core:3.27.6",
"org.jacoco:org.jacoco.core:0.8.14",
Expand Down
46 changes: 44 additions & 2 deletions maven_install.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL",
"__INPUT_ARTIFACTS_HASH": 1624596153,
"__RESOLVED_ARTIFACTS_HASH": 1478602772,
"__INPUT_ARTIFACTS_HASH": -620116506,
"__RESOLVED_ARTIFACTS_HASH": 1157173568,
"conflict_resolution": {
"com.google.code.gson:gson:2.8.6": "com.google.code.gson:gson:2.8.9",
"com.google.j2objc:j2objc-annotations:2.8": "com.google.j2objc:j2objc-annotations:3.1",
Expand Down Expand Up @@ -260,6 +260,12 @@
},
"version": "5.0.4"
},
"ognl:ognl": {
"shasums": {
"jar": "5ee6714ac10e66deabd80c15f3f7d4d733d5a7c99c0904d2e7b207c72221b475"
},
"version": "3.3.0"
},
"org.apache.commons:commons-imaging": {
"shasums": {
"jar": "64d649007364d70dcab24a1f895646e6976f5e2b339ba73a4af20642d041666a"
Expand Down Expand Up @@ -446,6 +452,12 @@
},
"version": "0.8.14"
},
"org.javassist:javassist": {
"shasums": {
"jar": "57d0a9e9286f82f4eaa851125186997f811befce0e2060ff0a15a77f5a9dd9a7"
},
"version": "3.28.0-GA"
},
"org.jboss.logging:jboss-logging": {
"shasums": {
"jar": "a3b0ffa8ae2b2f2387ebdfdce29086d3955d2a46ce7da802c2ba6ae47fa2f1bf"
Expand Down Expand Up @@ -745,6 +757,9 @@
"junit:junit": [
"org.hamcrest:hamcrest-core"
],
"ognl:ognl": [
"org.javassist:javassist"
],
"org.apache.commons:commons-jexl": [
"commons-logging:commons-logging"
],
Expand Down Expand Up @@ -1450,6 +1465,12 @@
"joptsimple.internal",
"joptsimple.util"
],
"ognl:ognl": [
"ognl",
"ognl.enhance",
"ognl.internal",
"ognl.security"
],
"org.apache.commons:commons-imaging": [
"org.apache.commons.imaging",
"org.apache.commons.imaging.color",
Expand Down Expand Up @@ -1916,6 +1937,25 @@
"org.jacoco.core.runtime",
"org.jacoco.core.tools"
],
"org.javassist:javassist": [
"javassist",
"javassist.bytecode",
"javassist.bytecode.analysis",
"javassist.bytecode.annotation",
"javassist.bytecode.stackmap",
"javassist.compiler",
"javassist.compiler.ast",
"javassist.convert",
"javassist.expr",
"javassist.runtime",
"javassist.scopedpool",
"javassist.tools",
"javassist.tools.reflect",
"javassist.tools.rmi",
"javassist.tools.web",
"javassist.util",
"javassist.util.proxy"
],
"org.jboss.logging:jboss-logging": [
"org.jboss.logging"
],
Expand Down Expand Up @@ -2772,6 +2812,7 @@
"net.bytebuddy:byte-buddy-agent",
"net.jodah:typetools",
"net.sf.jopt-simple:jopt-simple",
"ognl:ognl",
"org.apache.commons:commons-imaging",
"org.apache.commons:commons-jexl",
"org.apache.commons:commons-lang3",
Expand Down Expand Up @@ -2803,6 +2844,7 @@
"org.hamcrest:hamcrest-core",
"org.hibernate:hibernate-validator",
"org.jacoco:org.jacoco.core",
"org.javassist:javassist",
"org.jboss.logging:jboss-logging",
"org.jetbrains.kotlin:kotlin-reflect",
"org.jetbrains.kotlin:kotlin-stdlib",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ object ExpressionLanguageInjection {
private const val SPRING_EXPRESSION_LANGUAGE_ATTACK = "T($HONEYPOT_CLASS_NAME).el()"
private const val ELPROCESSOR_JEXL_LANGUAGE_ATTACK =
"\"\".getClass().forName(\"$HONEYPOT_CLASS_NAME\").getMethod(\"el\").invoke(null)"
private const val OGNL_LANGUAGE_ATTACK = "@$HONEYPOT_CLASS_NAME@el()"
private const val MVEL_ATTACK = "Runtime.getRuntime().exec(\"jazze\")"

init {
Expand All @@ -47,6 +48,9 @@ object ExpressionLanguageInjection {
require(ELPROCESSOR_JEXL_LANGUAGE_ATTACK.length <= 64) {
"Expression language exploit must fit in a table of recent compares entry (64 bytes)"
}
require(OGNL_LANGUAGE_ATTACK.length <= 64) {
"Expression language exploit must fit in a table of recent compares entry (64 bytes)"
}
require(MVEL_ATTACK.length <= 64) {
"MVEL exploit must fit in a table of recent compares entry (64 bytes)"
}
Expand Down Expand Up @@ -244,4 +248,65 @@ object ExpressionLanguageInjection {
}
Jazzer.guideTowardsContainment(message, MVEL_ATTACK, hookId)
}

@MethodHooks(
MethodHook(
type = HookType.BEFORE,
targetClassName = "ognl.Ognl",
targetMethod = "parseExpression",
),
MethodHook(
type = HookType.BEFORE,
targetClassName = "ognl.Ognl",
targetMethod = "getValue",
),
MethodHook(
type = HookType.BEFORE,
targetClassName = "ognl.Ognl",
targetMethod = "setValue",
),
MethodHook(
type = HookType.BEFORE,
targetClassName = "ognl.Ognl",
targetMethod = "isConstant",
),
MethodHook(
type = HookType.BEFORE,
targetClassName = "ognl.Ognl",
targetMethod = "isSimpleProperty",
),
MethodHook(
type = HookType.BEFORE,
targetClassName = "ognl.Ognl",
targetMethod = "isSimpleNavigationChain",
),
)
@JvmStatic
fun hookParseOgnlExpression(
method: MethodHandle?,
thisObject: Any?,
arguments: Array<Any>,
hookId: Int,
) {
if (arguments.isEmpty()) return
val expr = arguments[0] as? String ?: return
Jazzer.guideTowardsContainment(expr, OGNL_LANGUAGE_ATTACK, hookId)
}

@MethodHook(
type = HookType.BEFORE,
targetClassName = "ognl.Ognl",
targetMethod = "compileExpression",
)
@JvmStatic
fun hookCompileOgnlExpression(
method: MethodHandle?,
thisObject: Any?,
arguments: Array<Any>,
hookId: Int,
) {
if (arguments.size != 3) return
val expr = arguments[2] as? String ?: return
Jazzer.guideTowardsContainment(expr, OGNL_LANGUAGE_ATTACK, hookId)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ java_junit5_test(
"@maven//:javax_el_javax_el_api",
"@maven//:javax_persistence_javax_persistence_api",
"@maven//:javax_validation_validation_api",
"@maven//:ognl_ognl",
"@maven//:org_apache_commons_commons_jexl",
"@maven//:org_junit_jupiter_junit_jupiter_api",
"@maven//:org_junit_jupiter_junit_jupiter_params",
Expand Down
2 changes: 2 additions & 0 deletions sanitizers/src/test/java/com/example/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ java_fuzz_target_test(
"//sanitizers/src/test/java/com/example/el:ExpressionLanguageExample",
"@maven//:javax_el_javax_el_api",
"@maven//:javax_validation_validation_api",
"@maven//:ognl_ognl",
"@maven//:org_apache_commons_commons_jexl",
"@maven//:org_junit_jupiter_junit_jupiter_api",
"@maven//:org_mvel_mvel2",
Expand All @@ -76,6 +77,7 @@ java_fuzz_target_test(
"fuzzEval",
"fuzzJexlExpression",
"fuzzMVELExpression",
"fuzzOgnlExpression",
]]

java_fuzz_target_test(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import javax.el.ELProcessor;
import javax.validation.Validation;
import javax.validation.Validator;
import ognl.Ognl;
import org.apache.commons.jexl2.Expression;
import org.apache.commons.jexl2.JexlContext;
import org.apache.commons.jexl2.JexlEngine;
Expand Down Expand Up @@ -79,4 +80,14 @@ void fuzzMVELExpression(@NotNull String data) {
} catch (Throwable ignored) {
}
}

@FuzzTest
void fuzzOgnlExpression(@NotNull String data) {
try {
Object expression = Ognl.parseExpression(data);
Object root = new Object();
Ognl.getValue(expression, root);
} catch (Throwable ignored) {
}
}
}