Java: Unsafe RMI deserialization#5818
Conversation
| * Looks for a vulnerable method in a `Remote` object. | ||
| */ | ||
| private Method getVulnerableMethod(Type type) { | ||
| type.(RefType).getASupertype*() instanceof TypeRemote and |
There was a problem hiding this comment.
If I understand the documentation of Remote correctly, only methods declared in an interface which directly extends Remote are remote methods.
Therefore the following would probably not be vulnerable (though I am not sure):
interface RemoteInterface extends Remote {
void doSomething(int);
}
class RemoteClass implements RemoteInterface {
@Override
public void doSomething(int) {}
// Not vulnerable
public void doSomething(Object o) {}
}(So only methods declared on an Interface which has Remote as direct supertype might be vulnerable)
There was a problem hiding this comment.
Good catch! I'll update the query. Thanks!
java/ql/src/experimental/Security/CWE/CWE-502/RmiUnsafeDeserialization.ql
Outdated
Show resolved
Hide resolved
| import java | ||
| import semmle.code.java.frameworks.Rmi | ||
|
|
||
| private class ObjectInputStream extends RefType { |
There was a problem hiding this comment.
Could use more specific type here:
| private class ObjectInputStream extends RefType { | |
| private class ObjectInputStream extends Class { |
There was a problem hiding this comment.
Sure, I can use Class here. Do you know whether it would make the query faster or not?
There was a problem hiding this comment.
Using the most specific types is one recommendation of the CodeQL documentation.
Though I am not sure if there is actually a notable performance improvement, or how big the improvement will be, might be best to start a discussion if you want to get more detailed information from the maintainers.
java/ql/src/experimental/Security/CWE/CWE-502/RmiUnsafeDeserialization.ql
Outdated
Show resolved
Hide resolved
java/ql/src/experimental/Security/CWE/CWE-502/RmiSafeRemoteObject.java
Outdated
Show resolved
Hide resolved
|
@Marcono1234 @pwntester Thanks for the review! I'll address your comments soon. I am currently checking if a couple of other sinks and sanitizers from |
b1b9edf to
76d658f
Compare
76d658f to
d2e29fc
Compare
|
I found out that it is possible to set a deserialization filter by calling I've updated tests and docs. The query is ready for review. |
| not ma.getArgument([2, 4]) | ||
| .getType() | ||
| .(RefType) | ||
| .getASupertype*() | ||
| .hasQualifiedName("java.io", "ObjectInputFilter") and |
There was a problem hiding this comment.
Simpler to check the parameter type than to walk the class hierarchy from the actual argument type
There was a problem hiding this comment.
Good point. I'll update the query.
| </p> | ||
| <p> | ||
| It is also possible to set a process-wide deserialization filter. | ||
| The filter can be set by with <code>ObjectInputFilter.Config.setSerialFilter(ObjectInputFilter)</code> method, |
There was a problem hiding this comment.
Note that this query doesn't check for either of these mitigations
There was a problem hiding this comment.
Correct, it doesn't. I thought about covering these mitigations in the query. To prevent deserialization attacks here, ObjectInputFilter.Config.setSerialFilter() should be called before actual RMI calls happen. I am not sure whether this check can be implemented with CodeQL or not. It is even more complicated with the jdk.serialFilter property. The property has to be set before the classes for deserialization mechanism (ObjectInputStream and others) are loaded because the property is read only once when the mechanism is accessed for the first time.
I'd prefer to keep these mitigations here because they are still valid if used correctly.
Please let me know if you have an idea how to reliably check there mitigations in the query.
There was a problem hiding this comment.
Just noting in the qhelp that these are valid mitigations but the query isn't sensitive to them is enough
|
Thanks for the comments @smowton ! I've addressed them and also fixed a few errors in the qhelp. |
java/ql/src/experimental/Security/CWE/CWE-502/UnsafeDeserializationRmi.qhelp
Outdated
Show resolved
Hide resolved
Co-authored-by: Chris Smowton <smowton@github.com>
smowton
left a comment
There was a problem hiding this comment.
Guh, sorry for the delay, didn't notice you apply that change.
No problem. Thanks for the review! |
RMI uses the default Java serialization mechanism (in other words,
ObjectInputStream) to pass parameters in remote method invocations. If a remote method accepts complex parameters, then a remote attacker can send a malicious serialized object as one of the parameters. The malicious object gets deserialized without any check on the incoming data. In the worst case, it may let the attacker run arbitrary code remotely.I'd like to propose a new experimental query that looks for deserialization vulnerabilities in remote objects registered in am RMI registry.
Here are several issue found by the query: