高版本Fastjson:Getter调用限制及绕过方式探究
字数 1919 2025-08-29 22:41:10
Fastjson高版本Getter调用限制及绕过方式深入分析
前言
在Fastjson和Jackson等JSON库中存在原生反序列化链(Gadgets),能够触发任意对象的getter方法。高版本Fastjson对此进行了限制,本文将详细分析这些限制机制及可能的绕过方式。
高版本Getter调用限制分析
Jackson JSON库测试
- 使用
JsonNode#toString作为反序列化Gadget测试 - 最新版Jackson仍可使用该链子
- 序列化payload生成时需绕过
writeReplace方法检查
Fastjson测试
- 从2.0.27版本开始设置黑名单限制
- 黑名单中的类不会被调用getter方法
- 测试使用
ysomap反序列化框架生成payload失败
Fastjson黑名单检查机制
-
检查流程:
- 通过
EventListenerList类的add方法抛出异常触发toString调用 - 调用
JSONObject#toString方法 - 最终触发
BeanUtils#ignore方法进行黑名单检查
- 通过
-
黑名单检查细节:
- 检查类名是否在黑名单中(早期版本为明文,后续版本为hash值)
- 检查是否为代理类(如果是则解析其代理的类)
- 递归检查所有父类
-
核心检查点:
ObjectWriterCreatorASM#createObjectWriter中调用BeanUtils.declaredFields- 黑名单拦截后跳过处理
TemplateImpl类 - 导致无法调用
TemplateImpl#getOutputProperties
黑名单绕过技术
黑名单类替代方案
寻找不在黑名单中的类作为sink点:
com.mchange.v2.naming.ReferenceIndirector$ReferenceSerialized类LdapAttribute#getAttributeDefinition方法sun.print.UnixPrintServiceLookup#getDefaultPrintServicejavax.naming.spiContinuationDirContext#getTargetContextcom.sun.media.sound.JARSoundbankReader#getSoundbank
Fastjson与Jackson的Getter调用差异
| 特性 | Jackson | Fastjson |
|---|---|---|
| Getter获取方式 | 直接调用getDeclaredMethods,顺序不确定 |
获取后排序,按ASCII升序调用 |
| 调用稳定性 | 不稳定,可能因非预期getter报错 | 稳定,但可能因排序导致需要的getter被跳过 |
| 解决方案 | 使用代理工具类封装 | 需要其他绕过方式 |
Getter调用流程分析(Fastjson)
- 调用
getMethods获取所有类方法 - 筛选getter方法规则:
- 方法名长度大于3
- 以"get"开头
- 第四个字母大写
- 将getter方法按属性名ASCII值升序排序
- 按排序顺序调用getter方法
动态代理绕过技术
-
JdkDynamicAopProxy方式:
- 代理
TemplatesImpl对象 - 仅暴露需要的
getOutputProperties方法 - 代理接口
javax.xml.transform.Templates不在黑名单中
- 代理
-
AutowireUtils$ObjectFactoryDelegatingInvocationHandler:
- 类似
JdkDynamicAopProxy的反射调用机制 - 需要找到能返回恶意对象的代理类
- 可使用
JSONObject本身实现代理
- 类似
-
JSONObject代理实现:
JSONObject#invoke根据getter方法格式获取属性名- 从map中获取对应value值返回
- 可构造返回恶意
TemplateImpl对象的Gadget
总结与防御建议
-
攻击面:
- Fastjson高版本通过黑名单限制getter调用
- 但仍可通过黑名单绕过和动态代理技术突破限制
- 需要持续关注新的sink点和绕过技术
-
防御建议:
- 及时更新到最新版本
- 考虑使用白名单机制替代黑名单
- 禁用不必要的JSON反序列化功能
- 监控和拦截可疑的反序列化行为