Fastjson高版本动态代理绕过黑名单利用分析
背景介绍
在Fastjson 2.0.26及之前版本,存在一条仅依赖Fastjson的原生反序列化链,其核心是利用JsonArray类的toString方法。该方法会遍历调用其元素的任意公开getter方法,从而可以触发TemplatesImpl#getOutputProperties方法,加载恶意字节码实现代码执行。
但在Fastjson 2.0.27版本后,TemplatesImpl类被加入了黑名单,同时黑名单中的类不会被调用getter方法,导致该利用链无法直接使用。
绕过原理
虽然TemplatesImpl被禁用,但它实现了Templates接口,而该接口也定义了getOutputProperties方法。关键发现是:
- Fastjson的黑名单仅拦截
TemplatesImpl类的方法调用 - 对代理
Templates接口的代理类无限制 - 代理对象的方法调用不会被拦截
因此可以通过动态代理创建一个代理对象,通过InvocationHandler将方法调用转发到被黑名单限制的TemplatesImpl实例上,间接触发TemplatesImpl#getOutputProperties方法。
反序列化触发toString链
触发JsonArray.toString的几种方式:
- Xstring链或
HotSwappableTargetSource#equals链 BadAttributeValueExpException链EventListenerList链TextAndMnemonicHashMap链
在题目环境中,BadAttributeValueExpException、EventListenerList和TextAndMnemonicHashMap类都被过滤,因此选择Xstring链作为调用JsonArray.toString的起点。
动态代理实现
题目提供了MyProxy代理类和MyObject接口,其作用与ObjectFactoryDelegatingInvocationHandler类似:
// MyProxy代理类类似于ObjectFactoryDelegatingInvocationHandler
// MyObject接口类似于ObjectFactory接口
关键点在于MyProxy的invoke方法:
- 如果方法名不是
equals、hashCode、toString - 会尝试使用
objectFactory.getObject()方法获取对象 - 然后通过反射
method.invoke调用该对象的方法
完整利用链
- 通过Xstring链触发
JsonArray.toString toString方法遍历调用元素的getter方法- 遇到代理对象时,调用其
getOutputProperties方法 - 代理对象将调用转发到实际的
TemplatesImpl实例 - 触发
TemplatesImpl#getOutputProperties加载恶意字节码
EXP编写要点
由于环境不出网,需要针对Solon框架打入内存马。关键步骤:
- 创建恶意
TemplatesImpl类 - 构建代理对象包装
TemplatesImpl - 构造触发链的JSON数据
- 处理反序列化前的条件绕过:
- if条件绕过
X-Real-Ip: localhost请求头伪造
JSON解析差异利用
题目使用org.json.JSONObject而非Fastjson解析JSON,但可以利用其与Map解析的差异:
org.json.JSONObject处理逗号和分号的方式相同- 可以利用
@type进行绕过 - JSONObject.length实际上是调用map.size
替代toString触发方式
另一种触发toString的链子:
AlignmentAction.writeObject -> putValue -> firePropertyChange -> JSONArray.toString
关键步骤:
- 在
alignmentAction初始化时,构造函数链会调用AbstractAction.putValue - 将恶意键值存入
arrayTable - 序列化时写入键值对数量
- 反序列化时读取并
putValue - 通过修改字节码使键冲突,确保
oldValue和newValue都传入firePropertyChange - 反射修改
changeSupport不为null - 最终触发
JSONArray.toString
调用栈分析
JSONArray.toString -> 元素getter调用 -> 代理对象方法调用 -> InvocationHandler.invoke ->
TemplatesImpl.getOutputProperties -> 字节码加载执行
防御建议
- 升级到最新Fastjson版本
- 严格限制反序列化的类白名单
- 对动态代理的使用进行监控
- 检查所有实现了
Templates接口的类调用
总结
通过动态代理技术,可以绕过Fastjson高版本对特定类的黑名单限制,关键在于理解Fastjson黑名单的实现机制和动态代理的工作方式。这种利用方式展示了Java反序列化漏洞的复杂性和灵活性,也提醒开发者需要全面考虑各种可能的绕过方式。