内存马常见堆栈排查法
前置:Dump堆栈/线程快照
工具:jps
获取到现有的Java进程PID和进程名
使用 -l 展示PID和包名
工具:jstack
先获取到Java进程PID,使用jstack Dpid | grep -A Num Hpid(nid)
Dpid->十进制pid
Num->输出行
Hpid(nid)->十六进制pid,这里作为nid使用,nid为占用最大的线程号
工具:Memshell-scanner
https://github.com/c0ny1/java-memshell-scanner
获取Tomcat下的所有的存在的Servlet/Filter/Listener
可dump对应的class文件,可kill对应的Servlet/Filter/Listener
Servlet马
Servlet马的创建流程
- 创建恶意Servlet
- 用Wrapper对其进行封装
- 添加封装后的恶意Wrapper到StandardContext的children当中
- 添加ServletMapping将访问的URL和Servlet进行绑定
检测思路
获取servletPath / servletName / standardWrapper这些信息之后
- 通过
Class.forName进行类的加载 - 获取对应servlet类的classloader
- 通过对应的classloader调用getResource方法获取源文件
如果没有获取到文件就认为其可能为内存马
Filter马
Filter马的创建流程
只需要设置filterMaps、filterConfigs、filterDefs就可以注入恶意的filter
- filterMaps:一个HashMap对象,包含过滤器名字和URL映射
- filterDefs:一个HashMap对象,过滤器名字和过滤器实例的映射
- filterConfigs变量:一个ApplicationFilterConfig对象,里面存放了filterDefs
检测思路
思路大致相同,
- 遍历所有的
filter - 分别获取每一个
filter的filterName / filterClass / filterClassLoaderName等等信息 - 最后在结果输出中,调用了
classFileIsExists方法根据filterClass来判断是否存在有对应的filterClass的文件资源,有,则输出对应的path路径,没有,则说明可能为内存马
Listener马
Listener马的创建流程
- 首先获取到
StardardContext对象 - 之后创建一个实现了
ServletRequestListener接口的监听器类 - 再然后通过调用
StardardContext类的addApplicationEventListener方法进行Listener的添加
检测思路
与Fileter一致,获取信息,输出path