Upgrade to Pro — share decks privately, control downloads, hide ads and more …

MagicHat - Insomni'hack teaser 2018 writeup

Dhaval Kapil
February 26, 2018

MagicHat - Insomni'hack teaser 2018 writeup

Dhaval Kapil

February 26, 2018
Tweet

More Decks by Dhaval Kapil

Other Decks in Education

Transcript

  1. Challenge overview • Given a Jar (Java archive) file •

    Client application for Java RMI (Java version of RPC) • Server is hosted remotely
  2. Class structure • Artifact ◦ Broomstick ◦ Frog ◦ .

    ◦ . ◦ Wand ◦ Hat - contains an instance of HashBag where Artifacts can be added Broomstick, Frog, …., Wand, Hat all inherit from Artifact (an abstract class)
  3. Challenge goal • Given access to only those 3 functions,

    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.]
  4. Vulnerability • HashBag can contain any type of objects •

    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.
  5. • We can only craft the data members of the

    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)
  6. Libraries loaded Libraries used by client program (server will rely

    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.
  7. Java Reflection API • Code that can inspect other code

    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)
  8. org.apache.commons.collections.Transformer • Interface with one function: Object transform(Object input) •

    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
  9. InvokerTransformer • Takes a method name with optional parameters during

    initialization • On transform, calls that method for the object provided with the parameters
  10. LazyMap • A type of ‘Map’ which creates a value

    if there’s no value for the requested key • This generation is done through a ‘transformer’ on the ‘key’
  11. Primitive for executing shell system(command); In Java Runtime.getRuntime().exec(command); Slight difference:

    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.
  12. • Now, we have a primitive for running arbitrary commands

    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
  13. TiedMapEntry • A class implementing Map’s Entry interface - ‘Key

    Value Pair’ • Tied to an underline Map • TiedMapEntry(Map map, Key key) • getKey() { return key; } • getValue() { return map.get(key); } • setValue(value) { map.put(key, value); } • hashCode: ◦ public int hashCode() { final Object value = getValue(); return (getKey() == null ? 0 : getKey().hashCode()) ^ (value == null ? 0 : value.hashCode()); }
  14. HashMap • Hash based implementation of Map interface • Internally

    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’
  15. HashBag • A Collection that counts the number of times

    an object appears in the collection • Backed by an internal HashMap object ‘map’
  16. Approach • Create a TiedMapEntry with the underlying map as

    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