◦ . ◦ Wand ◦ Hat - contains an instance of HashBag where Artifacts can be added Broomstick, Frog, …., Wand, Hat all inherit from Artifact (an abstract class)
get remote shell [The solution is independent of the functioning provided by the three functions. It only relies on the fact that ‘Hat’ object can be sent to the server which contains a ‘HashBag’ object.]
Java RMI serializes and deserializes objects when transmitting over the network • Java serialization opens up possibilities for exploits similar to python’s pickle, ruby’s marshall and php’s serialization.
objects, not code or functions • Whatever types of objects we use, corresponding readObject() will be called • No trivial solution exists - No class has any readObject() function passing data members to the shell We have to somehow ‘chain’ existing code pieces (gadgets) that are called during the process of deserialization that achieve arbitrary code execution and craft our payload accordingly - Property Oriented Programming (similar to ROP)
on a superset of these) alongwith classes in each from where gadgets will be used: • JRE System Libraries (default, available in every Java program) - HashMap • commons-collections-3.2.2.jar - Transformer, ConstantTransformer, InvokerTransformer, ChainedTransformer, LazyMap, TiedMapEntry, HashBag • commons-lang3-3.7.jar The last two libraries are quite famous (part of Apache Software Foundation). Exact versions can be found by unzipping the given ‘jar’ file.
in the same system • API: ◦ java.lang.Object (abstracts an object) ▪ java.lang.Class (abstracts a class / interface) ▪ java.lang.reflect.AccessibleObject • java.lang.reflect.Method (abstracts a function)
Classes inherit from this to create concrete Transformers • A Transformer transforms an input object to an output object • Doesn’t change the input object • Mainly used for: ◦ Type conversion ◦ Extracting parts of an object
It does not redirect stdin/stdout to the shell and silently executes the command Difficult to construct gadgets to run this directly. Instead, we’ll use reflection API.
in shell • All our state is in object variables, no code! Hence, can be passed as part of a serialized object • Our goal is to somehow trigger `lazyMap.get(...)` during the deserialization process
stores entries in a ‘table’: ◦ Entry[] table • Look up and updates implemented by calculating a hash of the ‘key’ and indexing into the ‘table’. • While calculating hash, calls ‘hashCode’ for the underlying ‘key’
our `lazyMap` and key ‘foo’ • Create a HashBag instance • Set HashBag’s underlying HashMap’s entry table’s first entry’s key to be our TiedMapEntry. • Set hat’s HashBag to the one created above • During deserialization of the Hat following will happen: ◦ HashBag.readObject() // Hat has a HashBag ◦ HashMap.readObject() // HashBag has a HashMap ◦ HashMap.put(key, value) // Any entry read will be inserted in HashMap ◦ key.hashCode() <=> tiedMapEntry.hashCode() // Key here will be our TiedMapEntry ◦ tiedMapEntry.getValue() ◦ map.getKey(key) <=> lazeMap.get(“foo”) • Note: Here, we have a key value entry, who’s key is a TiedMapEntry