JavaWeb内存马实战排查:基于Arthas的Filter/Servlet型后门定位指南
在JavaWeb安全攻防对抗中,内存马(Memory Shell)已成为高级攻击者的首选武器。与传统文件型Webshell不同,内存马通过动态修改JVM运行时结构实现驻留,具有无文件落地、隐蔽性强、生命周期与Web应用同步等特点。本文将聚焦Tomcat环境下Filter/Servlet型内存马的实战排查,提供基于Arthas工具的完整诊断方案。
1. 内存马攻击特征与排查思路
1.1 内存马核心攻击路径
内存马通常通过以下三种方式注入:
- Servlet API注入:动态注册恶意Servlet组件
- Filter链污染:在过滤器链首部插入恶意Filter
- Listener劫持:利用事件监听机制执行恶意代码
以Filter型内存马为例,其攻击流程如下:
- 利用反序列化/RCE漏洞获取初始权限
- 通过反射获取StandardContext对象
- 创建包含恶意逻辑的Filter实现类
- 构造FilterDef和FilterMap对象
- 将恶意Filter插入过滤器链头部
1.2 关键排查指标
| 指标类型 | 具体表现 | 检测难度 |
|---|---|---|
| 异常URL映射 | 未在web.xml中声明的路由 | ★★☆☆☆ |
| 非标准类加载 | 非WebappClassLoader加载的组件 | ★★★☆☆ |
| 反射调用痕迹 | StandardContext的反射修改操作 | ★★★★☆ |
| 字节码特征 | 包含Runtime.exec等危险方法调用 | ★★★★★ |
| 行为特征 | 非常规的HTTP参数处理逻辑 | ★★★☆☆ |
2. Arthas排查实战
2.1 环境准备与基础命令
安装Arthas并附加到目标Java进程:
wget https://arthas.aliyun.com/arthas-boot.jar java -jar arthas-boot.jar关键基础命令:
# 查看已加载类概况 sc *.Servlet sc *.Filter # 检查MBean注册情况 mbean | grep -E "Servlet|Filter" # 查看类加载器结构 classloader -t2.2 Filter型内存马排查
步骤1:定位异常Filter
# 列出所有Filter实现类 sc --implement javax.servlet.Filter # 对比web.xml声明内容 cat $CATALINA_BASE/conf/web.xml | grep '<filter>'步骤2:分析可疑Filter
# 反编译可疑类(示例:可疑类名为evil.Filter) jad --source-only evil.Filter # 查看类加载来源 classloader -c <classloaderHash>步骤3:验证Filter映射
# 获取Filter映射关系 watch org.apache.catalina.core.StandardContext filterMaps2.3 Servlet型内存马排查
步骤1:发现异常Servlet
# 列出所有Servlet实现 sc --implement javax.servlet.Servlet # 检查未注册的Servlet jad org.apache.catalina.core.StandardContext servletMappings步骤2:分析Servlet逻辑
# 反编译可疑Servlet jad --source-only evil.Servlet # 查看URL映射 watch org.apache.catalina.core.StandardContext servletMappings2.4 内存取证与深度分析
堆内存转储分析:
# 生成堆转储文件 heapdump /tmp/tomcat_heap.hprof # 使用MAT分析(需独立安装) strings /tmp/tomcat_heap.hprof | grep -E "doFilter|service"字节码校验:
# 对比磁盘与内存中的类 jad --source-only javax.servlet.Filter > /tmp/Filter_source.txt diff /tmp/Filter_source.txt $CATALINA_HOME/lib/servlet-api.jar!javax/servlet/Filter.class3. 自动化排查脚本
3.1 Filter检测脚本
#!/bin/bash # 检测异常Filter arthas-boot.jar <<EOF sc --implement javax.servlet.Filter | grep -v "org.apache." | tee /tmp/filters.txt jad --source-only $(cat /tmp/filters.txt) | grep -l "Runtime.getRuntime()" /tmp/filters.txt EOF3.2 Servlet检测脚本
import subprocess import re def check_servlets(): result = subprocess.run(['java', '-jar', 'arthas-boot.jar', '--command', 'sc --implement javax.servlet.Servlet'], capture_output=True, text=True) servlets = [line.split()[0] for line in result.stdout.splitlines() if not line.startswith('org.apache.')] suspicious = [] for servlet in servlets: decompile = subprocess.run(['java', '-jar', 'arthas-boot.jar', '--command', f'jad --source-only {servlet}'], capture_output=True, text=True) if 'ProcessBuilder' in decompile.stdout or 'Runtime.exec' in decompile.stdout: suspicious.append(servlet) return suspicious3.3 内存马特征决策树
开始 ├─ 是否存在未在web.xml中声明的Filter/Servlet? │ ├─ 是 → 高危 │ └─ 否 → 进入下一步 ├─ 类是否由非WebappClassLoader加载? │ ├─ 是 → 高危 │ └─ 否 → 进入下一步 ├─ 字节码是否包含危险方法调用? │ ├─ 是 → 高危 │ └─ 否 → 进入下一步 └─ 是否在StandardContext中有动态修改痕迹? ├─ 是 → 高危 └─ 否 → 安全4. 防御与处置建议
4.1 即时处置措施
内存马清除:
# 使用c0ny1的java-memshell-scanner wget https://github.com/c0ny1/java-memshell-scanner/releases/download/v1.0/scanner.jar java -jar scanner.jar -p <PID> -k服务重启:
# 强制重启Tomcat(会清除所有内存马) $CATALINA_HOME/bin/shutdown.sh -force $CATALINA_HOME/bin/startup.sh
4.2 长期防御方案
架构层防护:
- 启用RASP(运行时应用自我保护)
- 部署WAF规则拦截可疑的反射调用请求
- 限制JVM的反射权限
运维监控:
# 定期扫描脚本示例 #!/bin/bash while true; do arthas-boot.jar --command 'sc *.Filter' | diff - filter_whitelist.txt sleep 3600 done提示:完整防御体系应结合静态规则检测(YARA)、动态行为监控(RASP)和流量分析(NTA)构建多层防护
5. 高级排查技巧
5.1 溯源攻击入口
# 检查最近修改的class文件 find $CATALINA_BASE/webapps -name "*.class" -mtime -1 # 分析access.log中的可疑请求 awk '$9 ~ /200/ {print $7}' $CATALINA_BASE/logs/localhost_access_log.* | sort | uniq -c | sort -nr5.2 深度字节码分析
使用JD-GUI或FernFlower反编译可疑类:
// 典型内存马特征代码片段 public void doFilter(ServletRequest req, ServletResponse res) { String cmd = req.getParameter("exec"); if(cmd != null) { try { Runtime.getRuntime().exec(cmd); } catch(Exception e) {} } }5.3 历史行为追溯
# 检查已卸载但仍有引用的类 vmtool --action getInstances --className evil.Filter --limit 10在真实对抗环境中,我们发现攻击者开始采用以下规避技术:
- 使用Java Agent技术实现无反射注入
- 通过JNI调用本地代码绕过检测
- 利用WebSocket等非HTTP协议通信
保持防御策略的持续演进是应对内存马威胁的关键。建议每季度更新一次检测规则,并定期进行红蓝对抗演练。