Vulnerability’s code - CVE-2021–35587.
During communication between two machines through RPC or RMI, parameters are packed into a message and sent over the network. This packing of parameters into a message is called marshalling. Conversely, these packed parameters are unpacked from the unmarshalling message.
[About
ObjectInputStream]…Other uses include passing objects between hosts using a socket stream or for marshalling and unmarshaling arguments and parameters in a remote communication system. 4
Root Cause
obj_stream = new ObjectInputStream(new ByteArrayInputStream(Base64.decode(requester.substring("object:".length()))));
return obj_stream.readObject()
The problem here is when some object is deserialised this way “object:<base64 data>” this data will be directly deserialised without any filtering.
"object:".length()- get the length of the stringobject:.requester.substring("object:".length())- read the contents ofrequesterstarting from the 6th character (because the length ofobject:is 7 and arrays/strings in Java are 0-based).Base64.decode(requester.substring("object:".length()))- read and base64 decode the acquired part ofrequesterstring.ByteArrayInputStream(Base64.decode(requester.substring("object:".length())))- deserialise the result of base64 decoding into aByteArrayInputStream.new ObjectInputStream(new ByteArrayInputStream(Base64.decode(requester.substring("object:".length()))))- turn into object. So, this line convertsByteArrayInputStreamintoObjectInputStream.return obj_stream.readObject()- read and return the object.
❗️
readObjectis not a built-in method forObjectInputStreamobjects! It’s a method of aSerializableinterface that will have different implementations in different applications. It takesObjectInputStreamas an argument and performs whatever deserialisation it requires:private void readObject(java.io.ObjectInputStream in). 6 So, the root cause for this problem is thereadObjectimplementation.
“This method can also be used to respond to the event of an object of that class being deserialised. An example of this method might be for a database manager object to automatically establish a connection to the database when it is deserialised into memory. Most Java serialisation exploits take advantage of the code within these readObject methods because the code is guaranteed to be executed during deserialisation.” 5
🛠 Tools
- Ysoserial
References
Expand…
1
Oracle Access Manager Pre-Auth RCE (CVE-2021–35587 Analysis)
2
java 8 deserialize base64 encoded string, Stackoverflow
3
ByteArrayInputStream to ObjectInputStream disappeared
4
5
Attacking Java Deserialization. A great and details article. Although, not quite sure why the author didn’t use a decompiler like ByteCodeViewer and analyses pure Java byte code.
6
public interface Serializable, docs
7
AppSecCali 2015: Marshalling Pickles
8
9
FINDING GADGETS LIKE IT’S 2015: PART 1, how to get from readObject() to Runtime.exec(). A great breakdown of this method that helps understanding Java deserialisation attacks that lead to RCE.
10
FINDING GADGETS LIKE IT’S 2015: PART 2, tbc from the 9.
