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 ofrequester
starting 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 ofrequester
string.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 convertsByteArrayInputStream
intoObjectInputStream
.return obj_stream.readObject()
- read and return the object.
❗️
readObject
is not a built-in method forObjectInputStream
objects! It’s a method of aSerializable
interface that will have different implementations in different applications. It takesObjectInputStream
as an argument and performs whatever deserialisation it requires:private void readObject(java.io.ObjectInputStream in)
. 6 So, the root cause for this problem is thereadObject
implementation.
“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.