Java安全:内存马的隐匿之影与查杀之道
好的,我现在需要帮用户总结一篇文章的内容,控制在100字以内。首先,我得仔细阅读用户提供的文章内容,理解其主要观点和结构。
这篇文章主要讨论了Java安全中的内存马问题,特别是Tomcat类型的内存马。作者详细介绍了几种内存马的类型,包括Servlet、Filter、Listener和Valve内存马,以及Java Agent注入的方法。每种类型的原理和实现方式都有所涉及。
接下来,文章还讨论了如何定位和查杀这些内存马,提到了一些工具和技术,比如流量特征分析、代码特征检测、使用特定工具如java-memshell-scanner和arthas等。最后,作者总结了自己的学习经历和未来的计划。
用户的要求是用中文总结内容,控制在100字以内,并且不需要特定的开头。因此,我需要提炼出文章的核心内容:内存马的类型、原理、注入方法以及查杀手段。
考虑到字数限制,我应该简明扼要地涵盖这些要点。可能的结构是先点明主题(Tomcat内存马),然后列出主要类型(Servlet、Filter等),接着提到注入方法(反射动态注册),最后提到查杀工具和技术。
现在开始组织语言:
“文章探讨了Tomcat内存马的原理与注入方法,包括Servlet、Filter、Listener及Valve类型,通过反射动态注册恶意组件实现持久化控制,并介绍了流量特征分析与代码特征检测等查杀手段。”
这样控制在50字左右,符合要求。
</think>
文章探讨了Tomcat内存马的原理与注入方法,包括Servlet、Filter、Listener及Valve类型,通过反射动态注册恶意组件实现持久化控制,并介绍了流量特征分析与代码特征检测等查杀手段。
2026-3-11 07:52:46
Author: www.freebuf.com(查看原文)
阅读量:0
收藏
导语
java安全的另一个主要板块来了,我这里主要说的是tomcat类型的内存马,这个是最基础的最经典的内存马,spring内存马的利用条件比较苛刻,毕竟高版本的spring就不支持jsp,就无法直接通过访问运行代码的方式注入,而是通过反序列化或rce间接改写项目代码实现注入。
说这么多什么是内存马,他的定义是什么?
java内存马的原理是先由客户端发起一个web请求,中间件的各个独立的组件如Listener、Filter、Servlet等组件会在请求过程中做监听、判断、过滤等操作,内存马利用请求过程在内存中修改已有的组件或者动态注册一个新的组件,插入恶意的shellcode达到持久化的控制服务器
Servlet 内存马
Servlet 内存马通过将恶意的 Servlet 类注入到 Web 容器的 Servlet 上下文中,使得 Web 容器在接收到特定请求时,调用该恶意 Servlet 执行恶意操作。
原理解析
tomcat的底层contextconfig函数会对注册的servlet注入到tomcat容器,其中webxml对象的servlets和servletsmappings保存的是注册的servlet名和路径映射关系

然后通过两个for循环将servlets和servletsmappings这两个变量进行处理

for循环核心代码

那么我们怎么找到这个context

其实这个context可以在HttpServletRequest类找到

context=HttpServletRequest.getServletContext.context.context
(ServletContext->applcontext->StandardContext)
实现
创建恶意Servlet类
获取context:StandardContext(通过反射)
从context获取Wrapper对象
将自己的Servlet封装进wrapper对象
将wrapper添加到上下文并设置映射路径
创建恶意Servlet类叫ShellServlet 功能是命令执行

从request中获取servletContext

从servletContext中获取applicationContext

从applicationContext中获取standardContext

从context获取Wrapper对象

将自己的Servlet封装进wrapper对象

将wrapper添加到上下文并设置映射路径

Filter 内存马
Filter 内存马通过将恶意的 Filter 类注入到 Web 容器的 Filter 链中,使得所有请求都会经过该恶意 Filter,从而执行恶意操作。

原理解析
在tomcat过滤器的机制是内部存在一个filer数组通过指针偏移依次调用过滤器

而对与数组的赋值时调用applicationfilterfactory类的addfilter函数

实现
创建恶意Filter类
获取context:StandardContext(通过反射)
通过反射获取StandardContext中的filterConfigs字段
创建FilterDef对象,设置Filter的名称、类名等信息。
创建FilterMap对象,设置Filter拦截的URL模式。
通过反射创建ApplicationFilterConfig对象,将StandardContext和FilterDef作为参数传入。
将Filter的名称和ApplicationFilterConfig对象添加到filterConfigs中。
恶意filter

反射StandardContext

动态注册

Listener 内存马
Listener 是 Java Web 应用程序中的监听器,用于监听 Web 容器中的各种事件,如 ServletContext、HttpSession 和 ServletRequest 的创建和销毁等。Listener 内存马通过将恶意的 Listener 类注入到 Web 容器的监听器列表中,当特定事件发生时,执行恶意操作

原理解析
StandardContext 对象的 addApplicationEventListener() 方法会把注册的恶意的lisener放进lisener数组从而进行调用执行

实现
动态创建一个Listener类,
通过反射获取StandardContext.applicationEventListenersList属性
将创建的类添加进applicationEventListenersList列表
申明恶意Listener类

反射StandardContext

调用addApplicationEventListener()方法

Valve内存马
在web中请求达到服务器后传递的顺序分别是Engine->Host->Context->Wrapper,但是传递过程并不是容器直接互相调用,而是通过每个容器内部的 管道(Pipeline) 和 阀门(Valve) 机制实现的。这种设计模式是 Tomcat 架构的核心精髓,它让请求像水流一样在容器层级间智能流动Valve 是可插拔的请求处理单元,每个 Valve 负责一项独立功能(如日志记录、权限检查、数据压缩等),它们就像水管上的控制阀

原理解析
Valve是阀门,那么Pipeline就是管道,每个容器内部都有一个专属的 Pipeline,每个Pipeline里面都有一个执行顺序位于最后的基础阀门,负责将请求传递到下层容器的Pipeline,同时我们又可以在每个管道中添加自定义的阀门

每个容器均支持getPipeline()方法方便我们要拿到容器内的pipeline对象

实现
动态创建一个valve类,
通过反射获取StandardContext.applicationEventListenersList属性
获取容器管道添加阀门类
创建恶意valve类

反射StandardContext

注册valve

Agent内存马
Java Agent 注入内存马的核心原理是利用 Instrumentation 和 ClassFileTransformer 接口修改或添加目标 JVM 中已加载的类的字节码,从而动态注册恶意的 Servlet、Filter 等组件,或者修改已有的 Servlet、Filter 的行为。 它不会修改磁盘上的文件,所有的修改都发生在内存中
其实个人感觉这个没有上面几个实用性强,上面几个可以用文件上传的方式jsp注入内存马,这个是需要有shell权限之后的操作,最多是权限维持的思路。
org.apache.catalina.core.ApplicationFilterChain 一般都是代替这个类
工具


下载:https://github.com/rebeyond/memShell
内存马定位和查杀
思路
流量特征
不存在这个路径但是状态码200
访问目录存在可以的特征?cmd=命令
代码特征
web.xml没有对应的信息组件信息
代码存在Runtime.getRuntime().exec()敏感函数
反射的动态注册Filter、Servlet、Listener 等组件
代码中可能存在 password, key, token 等字符串,用于身份验证
工具推荐
java-memshell-scanner
上传jsp访问即可
只能检测 Filter、Servlet 和 Listener 类型的内存马,无法检测其他类型的内存马,例如通过 Java Agent 技术注入的内存马

下载:https://github.com/c0ny1/java-memshell-scanner
arthas
阿里巴巴的进程分析工具也可以作为我们查找内存马的方法,相较于脚本,这个是手工寻找的,更严谨
启动找到项目进程
java -jar arthas-boot.jar

路由寻找,如果路径不存在可能是内存马
mbean | grep “name=/”

Servlet查找可疑的类
sc *.servlet

Filter查找可疑的类
sc *.Filter

把可疑的类反编译
jad --source-only 类名

下载class文件,本地分析
dump 类名

下载:https://arthas.aliyun.com/arthas-boot.jar
shell-analyzer
全图形化界面简单操作。

下载:https://github.com/4ra1n/shell-analyzer
结语
java安全的部分到这里就结束了,我已经把我所有掌握的知识和技术都写进了博客里面了,这个可能是我最后一次写博客了,之后可能众测挖到一些有趣的洞还会分享出来,让大家一起学习,我从大二开始学安全,现在大三严格来说两年不到,掌握这么多知识感谢一路走来的师傅,让我从一个什么都不会的计算机小白到还算入门安全的人。谢谢你们让我这么快的成长。我之后也会去实习,希望我们都有光明的未来,加油加油。
github:https://github.com/hkl1x
weixin:hkl1x666
文章来源: https://www.freebuf.com/articles/web/473158.html
如有侵权请联系:admin#unsafe.sh