如何通过BCEL链分析,对比setter与getter触发在FastJSON 1.2.47中的利用效果?

摘要:代码审计 | FastJSON 1.2.47 不出网利用 —— BCEL 链分析 | setter 与 getter 触发对比 环境:FastJSON 1.2.47JDK 8u65Tomcat 9.0.20IDEA 调试
代码审计 | FastJSON 1.2.47 不出网利用 —— BCEL 链分析 | setter 与 getter 触发对比 环境:FastJSON 1.2.47 / JDK 8u65 / Tomcat 9.0.20 / IDEA 调试 目录 前言 和 TemplatesImpl 链的区别 补充:FastJSON 的 getter/setter 扫描机制 环境准备 恶意类编写 字节码转换脚本 Payload 结构 调试跟踪 完整调用链总结 前言 上一篇 TemplatesImpl 链需要开启 SupportNonPublicField,因为 _bytecodes 这些字段是 private 的,FastJSON 默认碰不到,利用条件比较苛刻。 BCEL 链是针对这个问题的替代方案,用的全是 public 的 setter,不需要 SupportNonPublicField,利用条件宽松一些。 和 TemplatesImpl 链的区别 TemplatesImpl BCEL 是否需要 SupportNonPublicField ✅ 必须 ❌ 不需要 环境依赖 无 需要 Tomcat(tomcat-dbcp) 利用难度 条件苛刻 相对宽松 不需要 SupportNonPublicField 的原因很简单:BCEL 链用的全是 public 的 setter,setDriverClassName() 和 setDriverClassLoader() 都是公开方法,FastJSON 默认就能调到,不需要额外开 Feature。 代价就是依赖 Tomcat 环境,目标没有 tomcat-dbcp 依赖就打不了。 补充:FastJSON 的 getter/setter 扫描机制 在正式跟链之前,先把这个机制搞清楚,不然看 payload 会有很多疑问。 自动 getter 触发 FastJSON 反序列化完成之后,会主动扫描类里所有的方法,满足以下条件的 getter 会被自动调用,不需要在 JSON 里显式写对应字段: get 开头 ✅ 无参数 ✅ 返回值不是基本类型 ✅ 没有对应的 setter ✅ getConnection() 完美符合这四条,所以 payload 里根本不需要写 "connection" 字段,FastJSON 自己就会去调它。 举个对比例子,TemplatesImpl 链里的 payload 是这样的: 会触发 getOutputProperties(): 其实 _outputProperties 这个字段写不写都行,即使删掉了也依然能执行成功——因为 getOutputProperties() 同样满足自动扫描的条件,FastJSON 会自己触发它。 setter 触发 setter 的触发逻辑更直接,FastJSON 解析 JSON 字段的时候,对每一个 JSON 字段都会去找对应的 setter,找到了就调: JSON 里有 "driverClassName" → 找 setDriverClassName() → 调用 不需要任何特殊条件,但必须在 JSON 里显式写这个字段,FastJSON 不会主动扫描 setter。
阅读全文