Skip to content

Commit 1c2f0a5

Browse files
committed
feat: add ognl expression guidance hook
1 parent f104955 commit 1c2f0a5

File tree

6 files changed

+124
-2
lines changed

6 files changed

+124
-2
lines changed

MODULE.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ TEST_MAVEN_ARTIFACTS = [
8585
"jakarta.validation:jakarta.validation-api:3.0.2",
8686
"javax.persistence:javax.persistence-api:2.2",
8787
"junit:junit:4.13.2",
88+
"ognl:ognl:3.3.0",
8889
"org.apache.commons:commons-jexl:2.1.1",
8990
"org.assertj:assertj-core:3.27.6",
9091
"org.jacoco:org.jacoco.core:0.8.14",

maven_install.json

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL",
3-
"__INPUT_ARTIFACTS_HASH": 1624596153,
4-
"__RESOLVED_ARTIFACTS_HASH": 1478602772,
3+
"__INPUT_ARTIFACTS_HASH": -620116506,
4+
"__RESOLVED_ARTIFACTS_HASH": 1157173568,
55
"conflict_resolution": {
66
"com.google.code.gson:gson:2.8.6": "com.google.code.gson:gson:2.8.9",
77
"com.google.j2objc:j2objc-annotations:2.8": "com.google.j2objc:j2objc-annotations:3.1",
@@ -260,6 +260,12 @@
260260
},
261261
"version": "5.0.4"
262262
},
263+
"ognl:ognl": {
264+
"shasums": {
265+
"jar": "5ee6714ac10e66deabd80c15f3f7d4d733d5a7c99c0904d2e7b207c72221b475"
266+
},
267+
"version": "3.3.0"
268+
},
263269
"org.apache.commons:commons-imaging": {
264270
"shasums": {
265271
"jar": "64d649007364d70dcab24a1f895646e6976f5e2b339ba73a4af20642d041666a"
@@ -446,6 +452,12 @@
446452
},
447453
"version": "0.8.14"
448454
},
455+
"org.javassist:javassist": {
456+
"shasums": {
457+
"jar": "57d0a9e9286f82f4eaa851125186997f811befce0e2060ff0a15a77f5a9dd9a7"
458+
},
459+
"version": "3.28.0-GA"
460+
},
449461
"org.jboss.logging:jboss-logging": {
450462
"shasums": {
451463
"jar": "a3b0ffa8ae2b2f2387ebdfdce29086d3955d2a46ce7da802c2ba6ae47fa2f1bf"
@@ -745,6 +757,9 @@
745757
"junit:junit": [
746758
"org.hamcrest:hamcrest-core"
747759
],
760+
"ognl:ognl": [
761+
"org.javassist:javassist"
762+
],
748763
"org.apache.commons:commons-jexl": [
749764
"commons-logging:commons-logging"
750765
],
@@ -1450,6 +1465,12 @@
14501465
"joptsimple.internal",
14511466
"joptsimple.util"
14521467
],
1468+
"ognl:ognl": [
1469+
"ognl",
1470+
"ognl.enhance",
1471+
"ognl.internal",
1472+
"ognl.security"
1473+
],
14531474
"org.apache.commons:commons-imaging": [
14541475
"org.apache.commons.imaging",
14551476
"org.apache.commons.imaging.color",
@@ -1916,6 +1937,25 @@
19161937
"org.jacoco.core.runtime",
19171938
"org.jacoco.core.tools"
19181939
],
1940+
"org.javassist:javassist": [
1941+
"javassist",
1942+
"javassist.bytecode",
1943+
"javassist.bytecode.analysis",
1944+
"javassist.bytecode.annotation",
1945+
"javassist.bytecode.stackmap",
1946+
"javassist.compiler",
1947+
"javassist.compiler.ast",
1948+
"javassist.convert",
1949+
"javassist.expr",
1950+
"javassist.runtime",
1951+
"javassist.scopedpool",
1952+
"javassist.tools",
1953+
"javassist.tools.reflect",
1954+
"javassist.tools.rmi",
1955+
"javassist.tools.web",
1956+
"javassist.util",
1957+
"javassist.util.proxy"
1958+
],
19191959
"org.jboss.logging:jboss-logging": [
19201960
"org.jboss.logging"
19211961
],
@@ -2772,6 +2812,7 @@
27722812
"net.bytebuddy:byte-buddy-agent",
27732813
"net.jodah:typetools",
27742814
"net.sf.jopt-simple:jopt-simple",
2815+
"ognl:ognl",
27752816
"org.apache.commons:commons-imaging",
27762817
"org.apache.commons:commons-jexl",
27772818
"org.apache.commons:commons-lang3",
@@ -2803,6 +2844,7 @@
28032844
"org.hamcrest:hamcrest-core",
28042845
"org.hibernate:hibernate-validator",
28052846
"org.jacoco:org.jacoco.core",
2847+
"org.javassist:javassist",
28062848
"org.jboss.logging:jboss-logging",
28072849
"org.jetbrains.kotlin:kotlin-reflect",
28082850
"org.jetbrains.kotlin:kotlin-stdlib",

sanitizers/src/main/java/com/code_intelligence/jazzer/sanitizers/ExpressionLanguageInjection.kt

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ object ExpressionLanguageInjection {
3535
private const val SPRING_EXPRESSION_LANGUAGE_ATTACK = "T($HONEYPOT_CLASS_NAME).el()"
3636
private const val ELPROCESSOR_JEXL_LANGUAGE_ATTACK =
3737
"\"\".getClass().forName(\"$HONEYPOT_CLASS_NAME\").getMethod(\"el\").invoke(null)"
38+
private const val OGNL_LANGUAGE_ATTACK = "@$HONEYPOT_CLASS_NAME@el()"
3839
private const val MVEL_ATTACK = "Runtime.getRuntime().exec(\"jazze\")"
3940

4041
init {
@@ -47,6 +48,9 @@ object ExpressionLanguageInjection {
4748
require(ELPROCESSOR_JEXL_LANGUAGE_ATTACK.length <= 64) {
4849
"Expression language exploit must fit in a table of recent compares entry (64 bytes)"
4950
}
51+
require(OGNL_LANGUAGE_ATTACK.length <= 64) {
52+
"Expression language exploit must fit in a table of recent compares entry (64 bytes)"
53+
}
5054
require(MVEL_ATTACK.length <= 64) {
5155
"MVEL exploit must fit in a table of recent compares entry (64 bytes)"
5256
}
@@ -244,4 +248,65 @@ object ExpressionLanguageInjection {
244248
}
245249
Jazzer.guideTowardsContainment(message, MVEL_ATTACK, hookId)
246250
}
251+
252+
@MethodHooks(
253+
MethodHook(
254+
type = HookType.BEFORE,
255+
targetClassName = "ognl.Ognl",
256+
targetMethod = "parseExpression",
257+
),
258+
MethodHook(
259+
type = HookType.BEFORE,
260+
targetClassName = "ognl.Ognl",
261+
targetMethod = "getValue",
262+
),
263+
MethodHook(
264+
type = HookType.BEFORE,
265+
targetClassName = "ognl.Ognl",
266+
targetMethod = "setValue",
267+
),
268+
MethodHook(
269+
type = HookType.BEFORE,
270+
targetClassName = "ognl.Ognl",
271+
targetMethod = "isConstant",
272+
),
273+
MethodHook(
274+
type = HookType.BEFORE,
275+
targetClassName = "ognl.Ognl",
276+
targetMethod = "isSimpleProperty",
277+
),
278+
MethodHook(
279+
type = HookType.BEFORE,
280+
targetClassName = "ognl.Ognl",
281+
targetMethod = "isSimpleNavigationChain",
282+
),
283+
)
284+
@JvmStatic
285+
fun hookParseOgnlExpression(
286+
method: MethodHandle?,
287+
thisObject: Any?,
288+
arguments: Array<Any>,
289+
hookId: Int,
290+
) {
291+
if (arguments.isEmpty()) return
292+
val expr = arguments[0] as? String ?: return
293+
Jazzer.guideTowardsContainment(expr, OGNL_LANGUAGE_ATTACK, hookId)
294+
}
295+
296+
@MethodHook(
297+
type = HookType.BEFORE,
298+
targetClassName = "ognl.Ognl",
299+
targetMethod = "compileExpression",
300+
)
301+
@JvmStatic
302+
fun hookCompileOgnlExpression(
303+
method: MethodHandle?,
304+
thisObject: Any?,
305+
arguments: Array<Any>,
306+
hookId: Int,
307+
) {
308+
if (arguments.size != 3) return
309+
val expr = arguments[2] as? String ?: return
310+
Jazzer.guideTowardsContainment(expr, OGNL_LANGUAGE_ATTACK, hookId)
311+
}
247312
}

sanitizers/src/test/java/com/code_intelligence/jazzer/sanitizers/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ java_junit5_test(
2424
"@maven//:javax_el_javax_el_api",
2525
"@maven//:javax_persistence_javax_persistence_api",
2626
"@maven//:javax_validation_validation_api",
27+
"@maven//:ognl_ognl",
2728
"@maven//:org_apache_commons_commons_jexl",
2829
"@maven//:org_junit_jupiter_junit_jupiter_api",
2930
"@maven//:org_junit_jupiter_junit_jupiter_params",

sanitizers/src/test/java/com/example/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ java_fuzz_target_test(
6767
"//sanitizers/src/test/java/com/example/el:ExpressionLanguageExample",
6868
"@maven//:javax_el_javax_el_api",
6969
"@maven//:javax_validation_validation_api",
70+
"@maven//:ognl_ognl",
7071
"@maven//:org_apache_commons_commons_jexl",
7172
"@maven//:org_junit_jupiter_junit_jupiter_api",
7273
"@maven//:org_mvel_mvel2",
@@ -76,6 +77,7 @@ java_fuzz_target_test(
7677
"fuzzEval",
7778
"fuzzJexlExpression",
7879
"fuzzMVELExpression",
80+
"fuzzOgnlExpression",
7981
]]
8082

8183
java_fuzz_target_test(

sanitizers/src/test/java/com/example/ExpressionLanguageInjection.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import javax.el.ELProcessor;
2626
import javax.validation.Validation;
2727
import javax.validation.Validator;
28+
import ognl.Ognl;
2829
import org.apache.commons.jexl2.Expression;
2930
import org.apache.commons.jexl2.JexlContext;
3031
import org.apache.commons.jexl2.JexlEngine;
@@ -79,4 +80,14 @@ void fuzzMVELExpression(@NotNull String data) {
7980
} catch (Throwable ignored) {
8081
}
8182
}
83+
84+
@FuzzTest
85+
void fuzzOgnlExpression(@NotNull String data) {
86+
try {
87+
Object expression = Ognl.parseExpression(data);
88+
Object root = new Object();
89+
Ognl.getValue(expression, root);
90+
} catch (Throwable ignored) {
91+
}
92+
}
8293
}

0 commit comments

Comments
 (0)