当前位置: 首页 > news >正文

探究SpringWeb对于请求的处理过程

探究目的

在路径归一化被提出后,越来越多的未授权漏洞被爆出,而这些未授权多半跟spring自身对路由分发的处理机制有关。今天就来探究一下到底spring处理了什么导致了才导致鉴权被绕过这样严重的问题。

DispatcherServlet介绍

首先在分析spring对请求处理之前之前,首先需要了解DispatcherServlet,它是Spring MVC的核心,负责接收HTTP请求,并根据请求信息分发到相应的Controller进行处理。DispatcherServlet重要特性如下:

  • 前端控制器模式:在Spring MVC框架中,DispatcherServlet实现了前端控制器设计模式。这个模式的主要思想是提供一个中心点,所有的请求将先到达这个中心点,然后由它进行分发。这样可以帮助我们将请求处理流程中的公共逻辑集中处理,从而提高了代码的可维护性。

  • 请求分发:当DispatcherServlet接收到一个HTTP请求后,它会把请求分发给相应的处理器。这个分发的过程主要依赖HandlerMapping组件。HandlerMapping根据请求的URL找到对应的Controller。

  • 处理器适配:找到了正确的处理器之后,DispatcherServlet需要调用这个处理器的方法来处理请求。这个过程由HandlerAdapter负责。HandlerAdapter会调用处理器的适当方法,并将返回值包装成ModelAndView对象。

  • 视图解析:DispatcherServlet还负责将处理器返回的ModelAndView对象解析为实际的视图。这个过程由ViewResolver完成。视图解析器根据ModelAndView中的视图名和已配置的视图解析器来选择一个合适的视图。

Spring对于请求的处理顺序

在具体了解DispatcherServlet如何工作之前需要先了解java项目中各个组件对于url的处理顺序。

图片

看懂该图后,可以清晰地知道大多的路径归一化问题是因为鉴权的过滤器或者拦截器对于url的处理与spring最后对路由分发时的处理不一致,导致鉴权失败,从而可以未授权访问系统。下面就来看看springweb对url究竟是如何解析的

SpringWeb对于请求的处理过程

以springboot2.2x为例自己搭建一个springboot环境,创建好controller后在controller内部打断点。

在调用链中可以清晰地看到,spring对于url的分发确实是在filter之后,接下来

图片

从调用链可以看出在过完Filterchain链上所有的Filter后最后调用了DispatcherServlet的servlet方法。

这里牵扯到一个java的机制,(不想深入了解java的可以略过这段)首先servlet在ApplicationFilterChain.java的225行被反射赋值为DispatcherServlet对象。所以231行调用的是DispatcherServlet的service方法且传入的参数是ServletRequest,ServletResponse类型。但是在DispatcherServlet中并没有service方法,在DispatcherServlet的父类FrameworkServlet中也没有重写接收ServletRequest和ServletResponse的对象service方法,所以调用链到了上一级父类Httpservlet这个抽象类的service方法。Httpservlet中的service方法又调用了接收HttpServletRequest对象的service方法,该方法又被FrameworkServlet重写。故最后调用了FrameworkServlet中的service。完全符合上面的调用链顺序。这里比较绕,大家可以自己跟一下就明白了。网上有很多对于这里的介绍都是错误的,学安全嘛还是要刨根问底一下。源码如下

图片

图片

图片

接着可以看到FrameworkServlet的service方法中super调用了Httpservlet的service方法,值得注意的是在该方法中调用的doGet方法并不是Httpservlet的doGet方法,而是FrameworkServlet的doGet方法。

图片

图片

后面一直跟着调用链走,一直跟进到doDispatch方法。

在该方法中做了很多比较关键的处理。

首先处理了content-type为multipart的请求,后根据mappedHandler = getHandler(processedRequest);这行代码获取了已注册的handlerMappings。

图片

HandlerMapping是一个接口,负责将客户端的HTTP请求映射到对应的Controller。具体来说,它决定哪个Controller应该处理一个给定的请求。其中RequestMappingHandlerMapping用的最多,它支持@RequestMapping注解,并且通常与@Controller注解一起使用。

图片

所以具体处理的逻辑也就在getHandler方法中

图片

这段代码是从已注册的handlerMappings中获取一个HandlerExecutionChain对象,这个对象是对请求要执行的处理器以及其所有相关的拦截器的封装。跟进循环中的getHandler

图片

getHandlerInternal方法是将HTTP请求找到处理这个请求的Handler,然后将其包装到HandlerExecutionChain对象中,以便后续的处理流程。

到了这一步可以确定了,springweb对url的匹配是在getHandlerInternal之中,跟进getHandlerInternal看看其具体实现。

图片

看过路径归一化的师傅们应该到这里就很熟悉了,这个版本的函数叫getLookupPathForRequest,新版本叫initLookupPath。而这行代码也就是为了获得请求路径(通俗说就是我们请求的url)。看看他是怎么处理的

图片

很明显获取url的是 getRequestUri(request)

图片

跟入

图片

decodeAndCleanUriString这个函数可以说是大部分路径归一化问题的罪魁祸首,包括shiro 2020-1937也是因此而起。这三个函数我们挨个看看他到底干了什么

图片

removeSemicolonContentInternal主要做了两件事

1、移除所有的分号

2、移除分号后面直到下一个斜杠”/”之间的所有字符

图片

decodeRequestString函数是对url进行url解码,在这里也要强调一下,经常会看到有师傅用url编码进行鉴权绕过的情况也是由于此处的原因,在过滤器中其实并没有对编码过url进行处理,而到了spring分发路由的时候,却对他进行了解码从而绕过了认证。

顺便提一句,实战过程中可能会碰到Nginx的情况,Nginx也会对url进行一层解码。

图片

图片

getSanitizedPath把双/替换成单/

在此之中removeSemicolonContentInternal问题最大,由于前文处理的模型可以看到url先经过过滤器,如果过滤器中逻辑稍有不当,便有可能存在绕过鉴权的情况。

举个简单的例子

String requestUri =  request.getRequestURI();
If(requestUri.endsWith(“js”)){filterChain.doFilter(servletRequest, servletResponse);
}else{
return ;
}

这是一个常见的对静态文件不进行鉴权的过滤器,然而此时则可以通过/api/xxxxxx;js对该鉴权进行绕过。因为filter处理url时if是通过了if的逻辑,而到了spring的doDispatch中则由刚刚所述的处理,将其分发到了/api/xxxxxx正确对应的接口。

由此产生了很多鉴权问题,在filter之中对url处理稍有不慎变会导致该问题的产生。

再回到springweb对请求的处理,除了刚刚介绍的三个函数对请求的处理之外,还有个地方需要注意,在getLookupPathForRequest之中可以看到this.alwayUseFullPath。这个地方也是一个出现漏洞的点,在springboot2.3.0RELEASE之前spring是可以解析/api/a/../xxxx为/api/xxxx的,是因为this.alwayUseFullPath默认为false,而在springboot2.3.0RELEASE之后,this.alwayUseFullPath默认为true。将无法再解析/api/a/../xxxx,会直接认为该url是个路径,去匹配相应的controller。

图片

有始有终,刚刚只是解析获得了lookuppath也就是请求中的路径,之后再通过前文提到过的getHandlerInternal函数的lookupHandlerMethod对spring获取的url与controller中的url进行匹配。

放几张跟踪的图

图片

图片

图片

图片

图片

跟踪到最后还有个要注意的点,是关于后缀的匹配模式

图片

如果useSuffixPatternMatch为true,且spring配置文件中spring.mvc.pathmatch.use-suffix-pattern的值也为true(我的环境是springweb5.2图中为false)

图片

环境版本高,但是想实验的师傅可以自己配置一下

图片

Spring这时能解析/path/path.js

图片

在1.x版本的springboot和4.x版本的springweb中存在该情况。

该情况也会绕过很多鉴权过滤器,使过滤器误以为用户请求的是静态资源。

总结

常出现漏洞的点

1、removeSemicolonContentInternal函数对分号进行了相关处理导致绕过过滤器鉴权

2、decodeRequestString对url进行解码,此处也可能存在问题

3、在springboot2.3.0RELEASE之前alwayUseFullPath默认值为false,所以可能会导致"../","..;/"绕过鉴权的情况

4、springboot 1.x版本可以解析/path/path.js这类带有后缀的请求,可能造成鉴权绕过

参考链接

https://github.com/spring-projects/spring-framework/

https://forum.butian.net/share/2214

相关文章:

探究SpringWeb对于请求的处理过程

探究目的 在路径归一化被提出后,越来越多的未授权漏洞被爆出,而这些未授权多半跟spring自身对路由分发的处理机制有关。今天就来探究一下到底spring处理了什么导致了才导致鉴权被绕过这样严重的问题。 DispatcherServlet介绍 首先在分析spring对请求处…...

如何使用Google Compute Engine入门指南快速创建和配置您的云虚拟机实例

文章目录 步骤1:创建 Google Cloud Platform(GCP)账户步骤2:设置 GCP 项目步骤3:启用 Google Compute Engine API步骤4:安装 Google Cloud SDK步骤5:创建虚拟机实例步骤6:连接到虚拟…...

springMVC中全局异常处理

前言: 当不同方法执行时,抛出相同异常。为了简约代码和避免重复使用try{}catch{}。此时使用统一异常处理。但局部的统一异常处理只能为所在类所调用。因此产生全局异常处理,该类中统一异常处理方法可以作用于整个controller。(以…...

【Nginx24】Nginx学习:压缩模块Gzip

Nginx学习:压缩模块Gzip 又是一个非常常见的模块,Gzip 现在也是事实上的 Web 应用压缩标准了。随便打开一个网站,在请求的响应头中都会看到 Content-Encoding: gzip 这样的内容,这就表明当前这个请求的页面或资源使用了 Gzip 压缩…...

我的私人笔记(zookeeper分布式安装)

分布式安装 1.安装前准备 (1)下载zookeeper:Index of /dist/zookeeper(当前使用为3.4.10版本) (2)安装JDK (3)拷贝zookeeper安装包到Linux系统下 (4)解压到指定目录 tar -xzvf zookeeper-3.4.10.tar.gz -C /opt/servers/ (5)修改名称 …...

小程序排名优化全攻略

随着小程序的快速发展,小程序之间的竞争也日益激烈。如何在竞争对手众多的环境下脱颖而出,通过小程序排名优化来提高曝光率和流量转化率,已成为许多小程序开发者和运营者关注的重点。本文将全面解析小程序排名优化的方法,让您可以更好地提升小程序的搜索排名。 【名即微】 小程…...

MySQL MHA

什么是 MHA MHA(Master High Availability)是一套优秀的MySQL高可用环境下故障切换和主从复制的软件 MHA 的出现就是解决MySQL 单点故障的问题 MySQL故障切换过程中,MHA能做到0-30秒内自动完成故障切换操作 MHA能在故障切换的过程中最大程度上…...

Java API速记手册(持续更新ing...)

诸神缄默不语-个人CSDN博文目录 之所以干这个事原因也很简单,因为我3年没写Java了,现在在复健。 因为我最近都在用Python,所以跟Python一样的部分我就不写了。 最基本的框架public class MainClass {public static void main(String[] args…...

FANUC机器人电气控制柜内部硬件电路和模块详细介绍

FANUC机器人电气控制柜内部硬件电路和模块详细介绍 PSU电源单元 通过背板传输了如下电源 +5 +2.0V +3.3 +24v +24E +15V -15V 主板--接口描述: 主板内部结构: 面板电路板: 引申一下 KM21 与 KM22 的作用它们分别接至操作面板上上的急停按...

LGFormer:LOCAL TO GLOBAL TRANSFORMER FOR VIDEO BASED 3D HUMAN POSE ESTIMATION

基于视频的三维人体姿态估计的局部到全局Transformer 作者:马海峰 *,陆克 * †,薛健 *,牛泽海 *,高鹏程† * 中国科学院大学工程学院,北京100049 鹏程实验室,深圳518055 来源:202…...

数据结构零基础入门篇(C语言实现)

前言:数据结构属于C学习中较难的一部分,对应学习者的要求较高,如基础不扎实,建议着重学习C语言中的指针和结构体,万丈高楼平地起。 目录: 一,链表 1)单链表的大致结构实现 2&…...

Hugging News #0904: 登陆 AWS Marketplace

每一周,我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新,包括我们的产品和平台更新、社区活动、学习资源和内容更新、开源库和模型更新等,我们将其称之为「Hugging News」。本期 Hugging News 有哪些有趣的消息&#xff0…...

Redis Redis的数据结构 - 通用命令 - String类型命令 - Hash类型命令

目录 Redis的数据结构: Redis命令: 通用命令:(通用指令是部分数据类型的,都可以使用的指令) KEYS查询命令: DEL删除命令: EXISTS判断命令: EXPIPE有效期设置命令&…...

vue中的几种name属性

vue中的几种name属性 组件名name name选项 export default{name:xxx } // 获取组件的name属性 this.$options.namevue-devtools调试工具里显示的组件名称; 未配置name选项,就是组件的文件名; vue3配置name通过defineOptions()函数 de…...

论文《面向大规模日志数据分析的自动化日志解析》翻译

论文《Towards Automated Log Parsing for Large-Scale Log Data Analysis》翻译 面向大规模日志数据分析的自动化日志解析翻译...

element-ui dialog弹窗 设置点击空白处不关闭

根据官网提供方法 场景:vue实现的网站有两个弹窗同时出现时,关闭报警,批量进度条弹窗也关闭了, 1、每一个页面都有可能出现的报警弹窗, 2、页面a批量操控硬件添加操作的进度条弹窗 开始以为是因为点击报警弹窗&#…...

第16节-PhotoShop基础课程-修复工具组-去水印

文章目录 前言1.污点修复画笔1.功能原理2.调整1.调整大小 Alt 右键 左右2.调整软硬 Alt 右键 上下 2.修复画笔工具 Alt 选取源1.常规2.选择图案 3.修补工具1.类型1.源2.目标 2.扩展 4.内容感知移动工具5.红眼工具 前言 去水印等 1.污点修复画笔 比如把下面的土豆&#xff08…...

conda的使用教程

conda的介绍 简单来说,conda软件就是来管理包的软件。以Python为例,在实际生活中,我们要处理多个不同的项目,因此,要安装不同的项目所需要的包,为了管理方便,conda就是用来打理不同项目的包&…...

客户端发现pod并与之通信

客户端发现pod并与之通信 pod需要一种寻找其他pod的方法来使用其他pod提供的服务,不像在没有Kubernetes的世界,系统管理员要在用户端配置文件中明确指出服务的精确IP地址 或者主机名来配置每个客户端应用,但同样的方法在Kubernetes中不适用 …...

Powershell模拟实现Linux下的tree命令

Powershell模拟实现Linux下的tree命令 代码 环境: P o w e r s h e l l 7 Powershell\ 7 Powershell 7 function Get-Tree {param([string]$directory ".",[int]$d 1,[switch]$f)$absolutePath Resolve-Path -Relative $directoryWrite-Host $absol…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦&#xff0…...

省略号和可变参数模板

本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...

基于开源AI智能名片链动2 + 1模式S2B2C商城小程序的沉浸式体验营销研究

摘要&#xff1a;在消费市场竞争日益激烈的当下&#xff0c;传统体验营销方式存在诸多局限。本文聚焦开源AI智能名片链动2 1模式S2B2C商城小程序&#xff0c;探讨其在沉浸式体验营销中的应用。通过对比传统品鉴、工厂参观等初级体验方式&#xff0c;分析沉浸式体验的优势与价值…...

echarts使用graphic强行给图增加一个边框(边框根据自己的图形大小设置)- 适用于无法使用dom的样式

pdf-lib https://blog.csdn.net/Shi_haoliu/article/details/148157624?spm1001.2014.3001.5501 为了完成在pdf中导出echarts图&#xff0c;如果边框加在dom上面&#xff0c;pdf-lib导出svg的时候并不会导出边框&#xff0c;所以只能在echarts图上面加边框 grid的边框是在图里…...