Slide 1

Slide 1 text

MagicHat Insomni’hack teaser 2018

Slide 2

Slide 2 text

Challenge overview ● Given a Jar (Java archive) file ● Client application for Java RMI (Java version of RPC) ● Server is hosted remotely

Slide 3

Slide 3 text

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)

Slide 4

Slide 4 text

Java RMI (Remote Method Invocation)

Slide 5

Slide 5 text

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.]

Slide 6

Slide 6 text

Dummy Server

Slide 7

Slide 7 text

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.

Slide 8

Slide 8 text

Java Serialization

Slide 9

Slide 9 text

Java Serialization

Slide 10

Slide 10 text

● 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)

Slide 11

Slide 11 text

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.

Slide 12

Slide 12 text

Background ● Java Reflection API ● Transformers ● Lazy Map

Slide 13

Slide 13 text

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)

Slide 14

Slide 14 text

Java Reflection API

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

org.apache.commons.collections.Transformer

Slide 17

Slide 17 text

ConstantTransformer ● Always returns the same object specified during initialization

Slide 18

Slide 18 text

InvokerTransformer ● Takes a method name with optional parameters during initialization ● On transform, calls that method for the object provided with the parameters

Slide 19

Slide 19 text

ChainedTransformer ● Takes an array of transformers during initialization and chains them

Slide 20

Slide 20 text

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’

Slide 21

Slide 21 text

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.

Slide 22

Slide 22 text

Primitive for executing shell ● Runtime.getRuntime().exec(command);

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

● 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

Slide 26

Slide 26 text

Some more background ... ● TiedMapEntry ● HashMap ● HashBag

Slide 27

Slide 27 text

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()); }

Slide 28

Slide 28 text

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’

Slide 29

Slide 29 text

HashBag ● A Collection that counts the number of times an object appears in the collection ● Backed by an internal HashMap object ‘map’

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

Final Exploit

Slide 32

Slide 32 text

References https://github.com/p4-team/ctf/tree/master/2018-01-20-insomnihack/pwn_magic_h at [Writeup] https://www.youtube.com/watch?v=KSA7vUkXGSg [Talk on deserialization issues] https://github.com/frohoff/ysoserial [Collection of payloads and gadget chains for different libraries]