ermir: Evil Java RMI Registry
Ermir
Ermir is an Evil/Rogue RMI Registry, it exploits unsecure deserialization on any Java code calling standard RMI methods on it (list()/lookup()/bind()/rebind()/unbind()).
How does it work?
java.rmi.registry.Registry offers 5 methods: list(), lookup(), bind(), rebind(), unbind():
-
public Remote lookup(String name): lookup() searches for a bound object in the registry by its name, the registry returns a Remote object which references the remote object that was looked up, and the returned object is read using
MarshalInputStream.readObject()
which is just another layer on top of ObjectInputStream, basically it excpects after each class/proxy descriptor (TC_CLASSDESC/TC_PROXYCLASSDESC) an URL that will be used to load this class or proxy class. this is the same wild bug that was fixed in jdk7u21. (Ermir does not specify this URL as only old Java version are vulnerable, instead, it just write null). as Ysoserial gadgets are being serialized using ObjectOutputStream, Ermir uses gadgetmarshal -a wrapper around GadgetMarshaller.java– to serialize the specified gadget to match MarshalInputStream requirements. -
public String[] list(): list() asks the registry for all the bound objects names, while String type cannot be subsitued with a malicious gadget as it is not like any ordinary object and it is not read using readObject() but rather readUTF(), however as a list() returns String[] which is an actual object and it is read using
readObject()
, Ermir sends the gadget instead of this String[] type. -
public void bind(java.lang.String $param_String_1, java.rmi.Remote $param_Remote_2): bind() binds an object to a name on the registry, in the bind() case the return type is void and there is nothing being returned, however, if the registry specifies in the RMI return data packet that this return is an exceptional return, the client/server client will call
readObject()
despite the return type is void, this is how the registry sends exceptions to its client (usually java.lang.ClassNotFoundException), once again Ermir will deliver the serialized gadget instead of a legitimate Exception object. -
public void rebind(java.lang.String $param_String_1, java.rmi.Remote $param_Remote_2): rebind() replaces the binding of the passed name with the supplied remote reference, also returns void , Ermir returns an exception just like bind().
-
public void unbind(java.lang.String $param_String_1): unbind() unbinds a remote object by name in the RMI registry, this one also returns void.
Install & Use
Copyright (c) 2022 hakivvi