fastjson1.2.24代码分析

fastjson反序列化成因
fastjson 自动调用getter和setter
类似Java的反序列化过程会自动调用readObject函数,fastjson还原对象时也会自动调用以下几个函数:

无参数的构造函数
符合条件的getter函数
符合条件的setter函数

这里需要区别的是fastjson所使用的parse函数和parseObject函数所调用的函数条件是不一样的
代码浅析

        //通过parseObject,不指定类,返回的是一个JSONObject
        System.out.println("JSON.parseObject(serializedStr):");
        Object obj2 = JSON.parseObject(serializedStr);
        System.out.println("parseObject反序列化对象名称:" + obj2.getClass().getName());
        System.out.println("parseObject反序列化:" + obj2);
        System.out.println("-----------------------------------------------\n");

这是我们执行的代码,跟进parseObject()函数
在这里插入图片描述parseObject函数会首先调用JSON.parse函数,然后再去调用toJSON函数
这里toJSON会把obj套一层JSONObject对象,他的实现方法是先new一个JSONObject,把obj对象给填充进去;然后调用toJSONString把生成的JSONObject转化为json字符串;最后再调用parse函数将这个json字符串给还原。

这里的toJSONString是我们序列化的一个过程,他会去调用这个对象的所有getters,也就意味着parseObject函数会主动去调getters和setters,而parse函数则会调用这个对象的setters和符合条件的getters(这部分见后文)。

那么也就意味着,parseObject比parse函数多了一个调用所有getters的利用点

跟进parse函数
会走到com/alibaba/fastjson/parser/DefaultJSONParse#parse()函数
在这里插入图片描述
会在parseObject函数内解析传入的json数据
到了这里之后,开始依次进行JSON的解析,我们传入的第一个字符是{,所以进入case:12这个分支中,并继续进入parseObject(object, fieldName)方法来解析对象。
在这里插入图片描述
这个时候lexer所在的字符为",会进入下面这个分支继续解析JSON字符串,通过scanSymbol方法获取到双引号之间的字符串也就是@type
在这里插入图片描述
之后会获取@type字段的值,并且尝试获取这个类的Class,经过一系列的判断后,调用了deserializer.deserialize(this, clazz, fieldName)方法进行反序列化。

然后走在这里会反序列我们的数据
在这里插入图片描述
进入com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer.java#deserialz
方法
在这里插入图片描述
在第578行调用了createInstance函数,该函数将会对当前还原的类进行实例化,这里会自动调用无参数的构造函数
然后在第600行调用了parseField函数,该函数将对每个类属性进行初始化(或递归生成新的对象)
跟进parseField函数
在这里插入图片描述
这里调用了com/alibaba/fastjson/parser/deserializer/DefaultFieldDeserializer.java#parseField函数,直接看关键点第79行,调用了setValue函数
在这里插入图片描述
setValue函数就是fastjson自动调用getter和setter的关键点
在这里插入图片描述
如果不存在相应的getter、setter、is函数,则利用反射机制将value赋值到当前的object上(这里就是else部分做的事情)。

而当fieldInfo存在函数时,如果同时存在getter和setter,则调用setter,如果只存在getter则调用getter。

这里我们关注一下fieldInfo的method是怎么填充的呢?这里要看com/alibaba/fastjson/util/JavaBeanInfo.java#build函数,ParserConfig在createJavaBeanDeserializer函数中会调用JavaBeanInfo.build函数,以此填充fieldInfo,也就是我们需要分析的几个method。

不看具体的代码,写一下筛选的条件:
setter提取条件:
函数名长度大于等于4
非静态函数
限制返回类型为void或当前类
函数参数只有一个
函数名以set开头,第四个字符是大写或者unicde或者_或者字母f;如果函数名长度>=5,看第5位字符是不是大写的

getter提取条件:
函数名长度大于等于4
非静态函数
函数名以get开头,第四个字符大写
函数参数为0个
函数的返回类型为Collection的子类或本身、Map的子类或本身、AtomicBoolean、AtomicInteger、AtomicLong
无相对应的setter函数

经过上述的两个条件提取后,保留了符合条件的getter和setter,并于com/alibaba/fastjson/parser/deserializer/FieldDeserializer.java#setValue函数中invoke调用,也就是说实现了类似反序列化过程中主动调用readObject函数的效果。
知道了上述的条件,其实我们可以利用传入某字段的方式来主动调用相关符合条件的setter和getter。例如在Person里面添加一个setTest函数,并在需要转化的json中添加"test":1,将会主动调用setTest。
我们在利用@type构造有危害的利用链时,主要就是查找有危害的无参数的构造函数、符合条件的getter和setter。
fastjson更改反序列化漏洞对应有还几个版本,以后可下载其他版本的代码,往后几个小版本都是以黑名单的方式来限制,也就有了L和;绕过的可能,之后会后续分析,既然知道fastson是通过调用getter/setter来实现反序列化,那我们可以寻找能更改属性的类来构造我们想要达成的目的,这个后续分析

参考:
https://www.freebuf.com/vuls/178012.html
https://paper.seebug.org/994/#21-jsonstring
https://blog.0kami.cn/2020/04/13/java/talk-about-fastjson-deserialization/
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值