Hessian、Spring、Groovy、Rhino反序列化浅析
字数 2264 2025-08-23 18:31:24
Hessian、Spring、Groovy、Rhino反序列化漏洞分析与利用
1. Hessian反序列化漏洞
1.1 Hessian协议概述
Hessian是一种用于远程调用的二进制协议,具有以下特点:
- 广泛用于构建分布式系统中的跨平台通信
- 特别适用于Java语言,基于RPC协议
- 可以将Java对象序列化为二进制数据并通过网络传输
- 使用二进制格式,比XML或JSON等文本协议更高效
1.2 Hessian反序列化机制
Hessian基于Field机制进行反序列化,直接对Field进行赋值,而不是基于Bean机制调用getter/setter方法。
反序列化流程分析:
HessianInput#readObject()中通过Tag决定操作,序列化处理成Map形式,第一个code总是'M'(77)SerializerFactory#readMap获取反序列化器getDeserializer方法从缓存或_staticTypeMap获取反序列化器- 通过
sun.misc.Unsafe#allocateInstance初始化空对象 - 从
_fieldMap中获取对应Deserializer进行值恢复
1.3 利用条件
- 起始方法只能为
hashCode/equals/compareTo - 利用链中成员变量不能为
transient修饰 - 不依赖类中
readObject逻辑,也不依赖getter/setter逻辑
1.4 利用链示例
1.4.1 TemplatesImpl利用链
// 调用链
hessianinput.readObject()-> hashmap.put()-> EqualsBean.hashcode()-> ToStringBean.toString()->
SignedObject.getObject()-> hashmap.readObject()-> 后续利用链
1.4.2 JdbcRowSetImpl利用链
同样可以利用JNDI注入实现RCE。
1.5 特殊特性
Hessian支持反序列化任意类,无需实现Serializable接口,只需设置:
serializerFactory.setAllowNonSerializable(true);
2. Spring反序列化漏洞
2.1 Spring1反序列化链
2.1.1 关键类分析
-
AnnotationInvocationHandler:
invoke()方法从memberValues中取值- 可通过动态代理控制返回值
-
SerializableTypeWrapper$MethodInvokeTypeProvider:
readObject()中存在反射调用入口- 通过反射调用
this.provider.getType().getClass()的方法
-
ObjectFactoryDelegatingInvocationHandler:
invoke()方法从objectFactory调用getObject()- 通过
method.invoke调用类中的方法
2.1.2 完整利用链
SerializableTypeWrapper$MethodInvokeTypeProvider.readObject()
SerializableTypeWrapper.TypeProvider(Proxy).getType()
AnnotationInvocationHandler.invoke()
ReflectionUtils.invokeMethod()
Templates(Proxy).newTransformer()
AutowireUtils$ObjectFactoryDelegatingInvocationHandler.invoke()
ObjectFactory(Proxy).getObject()
TemplatesImpl.newTransformer()
2.2 Spring2反序列化链
2.2.1 关键类分析
-
JdkDynamicAopProxy:
- 继承
InvocationHandler接口 invoke()方法从AdvisedSupport获取TargetSource- 最终调用
AopUtils.invokeJoinpointUsingReflection()
- 继承
-
AopUtils:
invokeJoinpointUsingReflection()直接调用method.invoke()
2.2.2 完整利用链
SerializableTypeWrapper$MethodInvokeTypeProvider.readObject()
SerializableTypeWrapper.TypeProvider(Proxy).getType()
AnnotationInvocationHandler.invoke()
ReflectionUtils.invokeMethod()
Templates(Proxy).newTransformer()
JdkDynamicAopProxy.invoke()
AopUtils.invokeJoinpointUsingReflection()
TemplatesImpl.newTransformer()
3. Groovy反序列化漏洞
3.1 Groovy特性
Groovy是一种基于Java的动态语言,提供了execute()方法可直接执行命令:
"whoami".execute()
3.2 关键类分析
-
MethodClosure:
doCall()方法可触发InvokerHelper.invokeMethod()- 构造函数接收Object对象和Method名
-
ConvertedClosure:
- 继承
ConversionHandler和InvocationHandler invokeCustom()方法触发call()方法
- 继承
3.3 利用链
AnnotationInvocationHandler.readObject()
Map.entrySet() (Proxy)
ConversionHandler.invoke()
ConvertedClosure.invokeCustom()
MethodClosure.call()
ProcessGroovyMethods.execute()
4. Rhino反序列化漏洞
4.1 Rhino概述
Mozilla Rhino是基于Java的JavaScript引擎,可在JVM上运行JavaScript代码。
4.2 关键类分析
-
NativeError:
toString()触发js_toString()和getString()
-
ScriptableObject:
getProperty()和getImpl()方法链- 最终通过
MemberBox.invoke()反射调用
-
NativeJavaMethod:
call()方法查找并调用MemberBox数组
-
NativeJavaObject:
unwrap()方法返回javaObject- 自定义
read/writeObject()保存javaObject
4.3 利用链
BadAttributeValueExpException.readObject()
NativeError.toString()
ScriptableObject.getProperty()
ScriptableObject.getImpl()
NativeJavaMethod.call()
NativeJavaObject.unwrap()
MemberBox.invoke()
TemplatesImpl.newTransformer()
5. 防御措施
- 升级相关组件到最新安全版本
- 使用白名单机制限制反序列化的类
- 对输入数据进行严格验证和过滤
- 使用安全的序列化替代方案,如JSON
- 启用Java安全管理器限制权限
6. 总结
本文详细分析了Hessian、Spring、Groovy和Rhino四种反序列化漏洞的利用原理和技术细节,包括:
- Hessian的Field机制反序列化特性
- Spring框架中复杂的动态代理利用链
- Groovy语言特有的命令执行特性
- Rhino引擎中JavaScript与Java的交互机制
理解这些漏洞的利用原理有助于开发人员更好地防范反序列化攻击,构建更安全的应用程序。