0
点赞
收藏
分享

微信扫一扫

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析


文章目录

  • ​​写在前面​​
  • ​​JSONPath语法​​
  • ​​利用演示​​
  • ​​$ref引用触发get方法分析​​
  • ​​解释为什么1.2.36前的版本不行​​

写在前面

平时我们在处理fastjson反序列化的时候,如果我们想要执行属性的​​get​​​方法,而如果只有​​JSON.parse​​​怎么办
我们知道​​​JSON.parse​​​可以套一层​​parseObject​​​实现对​​get​​方法的调用,但说这个也没有必要继续本篇的介绍了,这里介绍另一种,废话不多说开始分析

JSONPath语法

看文档https://goessner.net/articles/JsonPath/,重点关注下这个

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_json

利用演示

人比较不老实,喜欢骚东西,这里执行下命令

public class Test {
private String cmd;

public String getCmd() throws IOException {
Runtime.getRuntime().exec(cmd);
return cmd;
}

public void setCmd(String cmd) {
this.cmd = cmd;
}
}

触发

public static void main(String[] args) {
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
String payload = "[{\"@type\":\"com.yyds.Test\",\"cmd\":\"calc\"},{\"$ref\":\"$[0].cmd\"}]";
Object o = JSON.parse(payload);
}

最爱的计算器

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_java_02

$ref引用触发get方法分析

简简单单引入依赖

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.36</version>
</dependency>

老规矩拉到底,看看调用栈再分析

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_get方法_03


跟进​​handleResovleTask​​函数

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_get方法_04


获取​​$ref​

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_get方法_05


至于如果你问在哪里设置的在​​DefaultJSONParser#parse()​

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_json_06

ok,不说废话,继续看下去,满足条件跟进

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_get方法_07


这里面没有返回​​null​

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_java_08


接下来重点来了,我们看看​​JSONPath.eval​​函数干了什么

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_java_09


跟进​​compile​

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_get方法_10

根据​​path​​​生成并返回一个​​JavaPath​​对象

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_get方法_11


继续看看​​eval​

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_get方法_12


这里有一个​​init​​函数执行

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_java_13


我们重点关注这个​​explain​​函数,把​​$ref​​的​​value​​解析成​​Segment​​,这个​​Segment​​是定义在​​JSONPath​​类的一个接口,具体看他的过程

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_json_14


这里初始化长度是8很好奇吗

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_json_15


因为实现​​segment​​接口的类只有八个

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_调用栈_16


ok,继续看看这个​​readSegement​​​,获取​​.​​后面的值

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_get方法_17


这里通过​​readName​​​获取到​​cmd​

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_调用栈_18


内部实现靠循环追加到​​StringBuilder​​后面

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_get方法_19


后面通过浅拷贝赋值返回

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_get方法_20


接下来按顺序执行前面​​explain​​生成的​​Segment array​

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_调用栈_21


跟进​​JSONPath.getPropertyValue​

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_调用栈_22


继续跟进

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_json_23


跟进

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_调用栈_24


后面就是用反射调用​​get​​方法了

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_get方法_25


[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_调用栈_26


分析完毕

解释为什么1.2.36前的版本不行

我们知道关键在于​​JSONPath.eval​​方法的调用

我们来对比一下,前为1.2.36版本,后为1.2.35版本

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_get方法_27

[Java安全]Fastjson>=1.2.36$ref引用可触发get方法分析_json_28


限制了​​refValue​​​的值不能为​​null​​​,并且必须是​​JSONObject​​对象,那就结束了


举报

相关推荐

0 条评论