Jvm killed by request parameter that change interal representation of String
KarolBedkowski opened this issue · comments
Hello,
Problem detected during migration some code from Jodd 4.x to 5.x.
Tested on version 5.0.10, app based on Joy.
Version 4.x is not affected.
Current behavior
Wrong/prepared request query parameter name can kill jvm.
Example 1:
@Action
public TextResult execute(@In final String action) {
...
}
Request /execute?action.value=
(empty value) create String object with internal field value
= null, and crash whole jvm with i.e, siginfo: si_signo: 11 (SIGSEGV), si_code: 1 (SEGV_MAPERR)
on String::equal, String::length or similar.
This same method can change internal hash value of string, etc.
Example 2:
@Action
public void execute(@In final SomeClass action) {
}
class SomeClass {
@In("param.value")
String param;
...
}
Request /execute?action.param.value=
- also set SomeClass::param
to invalid string;
In this case, change field name to i.e. paramValue solve problem.
Expected behavior
Internal representation of basic types like String should not be changed by request parameters.
Steps to Reproduce the Problem
Create simple action with one String parameter a
and i.e. log this parameter.
Call this action with query ?a.value=
.
wow, Jodd killed JVM :) I am on this!
Some more informationen would be nice:
- OS
- Java Version
- any special Java Flags are set? (like -XX ....)
- mini example project to reproduce your issue easily
Thanx!
Hi,
Sample project https://github.com/KarolBedkowski/joddt1 (include some logs)
Test with:
curl http://localhost:8080/userAjax.actions.json?query.value=
curl http://localhost:8080/userAjax.actions.json?dt.search.value=
OS: Debian Stable + OpenJDK 1.8; Debian SID + OpenJDK 11.0.3+4-1 / OpenJDK 8u212-b01-1 / Oracle JDK 1.8.0_102-b14 ; Windows 7 + Oracle Java 8
No special flags, env variables.
Tested with jetty maven plugin (jetty:run) and Tomcat 8.5.20 (deployed war).
Ok, so here is what is going on.
Calling the action.value
where action
is a String
will actually try to set the value
field of a String
. This is not something you would like to do :)
Why do you call /execute?action.value=
? You should call just /execute?action=
.
On the other hand, I guess Jodd should prevent such cases. So this is the issue with the BeanUtil
.
Test to recreate:
static class Foo {
public String s;
}
@Test
void testString() {
final Foo foo = new Foo();
BeanUtil.declaredForced.setProperty(foo, "s.value", null);
}
I guess we can add a check for core Java classes (if they are from java.*
package)
I agree - it's wrong call, I found this by accident (DataTable send ajax request with parameters like dt.search.value, and I have class with only "String search;"). In Jodd4 - this request don't generate any errors (I'm not sure in this moment, but I guess this simple work (.value was ignored)). But in Jodd5 I have crash.
But user/error in code can generate bad request like this. So this should be somehow handled IMHO.
Thanks.
Yes, it is an easy fix at the end. No fields will be accessible for java.*
classes.
And thank you very much for reporting @KarolBedkowski! The fix is on the way, and I will release fixed Jodd until Monday! :)