漏洞分析 Spring Framework路径遍历漏洞(CVE-2024-38816)
漏洞概述
VMware Spring Framework是美国威睿(VMware)公司的一套开源的Java、JavaEE应用程序框架。该框架可帮助开发人员构建高质量的应用。
近期,监测到Spring Framework在特定条件下,存在目录遍历漏洞(网宿评分:高危、CVSS 3.1 评分:7.5):
当同时满足使用 RouterFunctions 和 FileSystemResource 来处理和提供静态文件时,攻击者可构造恶意请求遍历读取系统上的文件。
目前该漏洞POC状态已在互联网公开,建议客户尽快做好自查及防护。
受影响版本
Spring Framework 5.3.0 - 5.3.39
Spring Framework 6.0.0 - 6.0.23
Spring Framework 6.1.0 - 6.1.12
其他更旧或者官方已不支持的版本
漏洞分析
根据漏洞描述(https://spring.io/security/cve-2024-38816)可知,关键变更在于如何处理静态资源路径。
https://github.com/spring-projects/spring-framework/commit/d86bf8b2056429edf5494456cffcb2b243331c49#diff-25869a3e3b3d4960cb59b02235d71d192fdc4e02ef81530dd6a660802d4f8707R4
这里改了两处,分别是:
webflux --> org.springframework.web.reactive.function.server.PathResourceLookupFunction
webmvc --> org.springframework.web.servlet.function.PathResourceLookupFunction
它们都旨在为 Web 应用程序提供静态内容的访问。
以webmvc --> org.springframework.web.servlet.function.PathResourceLookupFunction为例,展开分析。
先是动态处理了资源请求,确保只返回有效并且可访问的资源。
@Override
public Optional<Resource> apply(ServerRequest request) {PathContainer pathContainer = request.requestPath().pathWithinApplication();if (!this.pattern.matches(pathContainer)) {return Optional.empty();}pathContainer = this.pattern.extractPathWithinPattern(pathContainer);String path = processPath(pathContainer.value());if (path.contains("%")) {path = StringUtils.uriDecode(path, StandardCharsets.UTF_8);}if (!StringUtils.hasLength(path) || isInvalidPath(path)) {return Optional.empty();}try {Resource resource = this.location.createRelative(path);if (resource.isReadable() && isResourceUnderLocation(resource)) {return Optional.of(resource);}else {return Optional.empty();}}catch (IOException ex) {throw new UncheckedIOException(ex);}
}
接着对路径字符串进行规范化处理,确保返回的路径格式是有效的。
private String processPath(String path) {boolean slash = false;for (int i = 0; i < path.length(); i++) {if (path.charAt(i) == '/') {slash = true;}else if (path.charAt(i) > ' ' && path.charAt(i) != 127) {if (i == 0 || (i == 1 && slash)) {return path;}path = slash ? "/" + path.substring(i) : path.substring(i);return path;}}return (slash ? "/" : "");
}
最后从安全角度,确保路径不指向敏感目录,并且避免出现路径穿越的情况。
private boolean isInvalidPath(String path) {if (path.contains("WEB-INF") || path.contains("META-INF")) {return true;}if (path.contains(":/")) {String relativePath = (path.charAt(0) == '/' ? path.substring(1) : path);if (ResourceUtils.isUrl(relativePath) || relativePath.startsWith("url:")) {return true;}}return path.contains("..") && StringUtils.cleanPath(path).contains("../");
}
简单阐明以后,不难发现上述代码做了敏感目录检查、url检查、路径穿越检查等操作,暂时没发现可疑点,所以我们需要进一步跟进
org.springframework.web.servlet.function.PathResourceLookupFunction#isInvalidPath()
查看一下它检查相对路径时,StringUtils.cleanPath()做了哪些操作。
public static String cleanPath(String path) {if (!hasLength(path)) {return path;}String normalizedPath;// Optimize when there is no backslashif (path.indexOf('\') != -1) {normalizedPath = replace(path, DOUBLE_BACKSLASHES, FOLDER_SEPARATOR);normalizedPath = replace(normalizedPath, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR);}else {normalizedPath = path;}String pathToUse = normalizedPath;// Shortcut if there is no work to doif (pathToUse.indexOf('.') == -1) {return pathToUse;}// Strip prefix from path to analyze, to not treat it as part of the// first path element. This is necessary to correctly parse paths like// "file:core/../core/io/Resource.class", where the ".." should just// strip the first "core" directory while keeping the "file:" prefix.int prefixIndex = pathToUse.indexOf(':');String prefix = "";if (prefixIndex != -1) {prefix = pathToUse.substring(0, prefixIndex + 1);if (prefix.contains(FOLDER_SEPARATOR)) {prefix = "";}else {pathToUse = pathToUse.substring(prefixIndex + 1);}}if (pathToUse.startsWith(FOLDER_SEPARATOR)) {prefix = prefix + FOLDER_SEPARATOR;pathToUse = pathToUse.substring(1);}String[] pathArray = delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR);// we never require more elements than pathArray and in the common case the same numberDeque<String> pathElements = new ArrayDeque<>(pathArray.length);int tops = 0;for (int i = pathArray.length - 1; i >= 0; i--) {String element = pathArray[i];if (CURRENT_PATH.equals(element)) {// Points to current directory - drop it.}else if (TOP_PATH.equals(element)) {// Registering top path found.tops++;}else {if (tops > 0) {// Merging path element with element corresponding to top path.tops--;}else {// Normal path element found.pathElements.addFirst(element);}}}// All path elements stayed the same - shortcutif (pathArray.length == pathElements.size()) {return normalizedPath;}// Remaining top paths need to be retained.for (int i = 0; i < tops; i++) {pathElements.addFirst(TOP_PATH);}// If nothing else left, at least explicitly point to current path.if (pathElements.size() == 1 && pathElements.getLast().isEmpty() && !prefix.endsWith(FOLDER_SEPARATOR)) {pathElements.addFirst(CURRENT_PATH);}final String joined = collectionToDelimitedString(pathElements, FOLDER_SEPARATOR);// avoid string concatenation with empty prefixreturn prefix.isEmpty() ? joined : prefix + joined;
}
这个方法主要对用户输入路径做了规范化处理,具体包括长度检查、不同操作系统下的路径分隔符处理等。看起来也做了严格的处理,但这一步存在问题。
String[] pathArray = delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR);
具体来说,它是允许空元素存在的,假设路径字符串形如:
String pathToUse = “/static///…/…/Windows/win.ini”;
那么调用 delimitedListToStringArray 方法以后,pathArray即为
[“static”, “”, “”, “…”, “…”, “Windows”, “win.ini”]
而pathElements即为

再来看这一串:String pathToUse = “/static/…/…/Windows/win.ini”;

显然,pathArray中存在空元素会影响上级目录的处理,导致返回不同的结果,即存在安全隐患。
漏洞复现
实现目录穿越需要用到"…/",结合上述分析,可通过这种方式实现。
package org.example.demo;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;public class test {
public static void main(String[] args) {
String path = “/static///…/…/Windows/win.ini”;
System.out.println(isInvalidPath(path));
}private static boolean isInvalidPath(String path) {
if (path.contains(“WEB-INF”) || path.contains(“META-INF”)) {
return true;
}
if (path.contains(“😕”)) {
String relativePath = (path.charAt(0) == ‘/’ path.substring(1) : path);
if (ResourceUtils.isUrl(relativePath) || relativePath.startsWith(“url:”)) {
return true;
}
}
return path.contains(“…”) && StringUtils.cleanPath(path).contains(“…/”);
}
}

但还需要结合上下文,继续构造payload。首先路径以斜杠开头时,StringUtils.cleanPath()方法会去掉路径的第个斜杠。
if (pathToUse.startsWith(FOLDER_SEPARATOR)) {prefix = prefix + FOLDER_SEPARATOR;pathToUse = pathToUse.substring(1);
}
那就需要多写一条"/“,构造”///…/"跳一级目录。
而在最初的org.springframework.web.servlet.function.PathResourceLookupFunction#apply()中,对路径做了规范化处理,即去掉连续的"/"
pathContainer = this.pattern.extractPathWithinPattern(pathContainer);
String path = processPath(pathContainer.value());
所以需要将多余的"/“变为”",再借助StringUtils.cleanPath()方法重新转换回来。
normalizedPath = replace(normalizedPath, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR);

修复方案
目前官方已有可更新版本,建议受影响用户升级至最新版本:
https://github.com/spring-projects/spring-framework/tags
产品支持
网宿全站防护-WAF已支持对该漏洞利用攻击的防护,并持续挖掘分析其他变种攻击方式和各类组件漏洞,第一时间上线防护规则,缩短防护“空窗期”。
相关文章:
漏洞分析 Spring Framework路径遍历漏洞(CVE-2024-38816)
漏洞概述 VMware Spring Framework是美国威睿(VMware)公司的一套开源的Java、JavaEE应用程序框架。该框架可帮助开发人员构建高质量的应用。 近期,监测到Spring Framework在特定条件下,存在目录遍历漏洞(网宿评分&am…...
《手札·避坑篇》2025年传统制造业企业数字化转型指南
一、引言 在数字化浪潮的推动下,传统制造业企业正加速向智能化、数字化转型。开源软件技术与制造MES(制造执行系统)产品的结合,为企业提供了高效、灵活且低成本的转型路径。本指南旨在为传统制造业企业的信息化负责人提供一套完整的数字化转型方案,助力企业实现高效、智能…...
MySQL中DDL操作是否支持事务
MySQL中DDL不支持事务。 传统MySQL(5.7及以前版本): DDL操作不支持事务执行DDL操作时会隐式提交当前会话的事务无法回滚DDL操作 MySQL 8.0版本: 引入了原子DDL特性(Atomic DDL)DDL操作变为原子性的&…...
GWO优化决策树回归预测matlab
灰狼优化算法(Grey Wolf Optimizer,简称 GWO)是一种群智能优化算法,由澳大利亚格里菲斯大学的 Mirjalii 等人于 2014 年提出。该算法的设计灵感源自灰狼群体的捕食行为,核心思想是模仿灰狼社会的结构与行为模式。 在本…...
掌握Spring @SessionAttribute:跨请求数据共享的艺术
SessionAttribute注解在Spring中的作用,就像是一个“数据中转站”。 在Web应用中,我们经常需要在多个请求之间共享数据。比如,用户登录后,我们需要在多个页面或请求中保持用户的登录状态。这时,SessionAttribute注解就…...
python读取Excel表格内公式的值
背景:在做业务周报的时候,有一个Excel模板,表里面包含了一些公式,dataframe写入到Excel的时候,有公式的部分通过python读出来的结果是None,需要进行优化参考链接: 如何使用openpyxl读取Excel单元…...
第三十八章:阳江自驾之旅:挖蟹与品鲜
经历了惠州海边那趟温馨又欢乐的自驾之旅后,小冷和小颖心中对旅行的热情愈发高涨。闲暇时,两人总会坐在客厅里,翻看着旅行杂志,或是在网上搜索各地的美景,那些充满魅力的地方不断吸引着他们,也让他们对下一…...
C++小等于的所有奇数和=最大奇数除2加1的平方。
缘由 三种思路解题:依据算术推导得到一个规律:小等于的所有奇数和等于最大奇数除以2加1的平方。将在后续发布,总计有十种推导出来的实现代码。 int a 0,aa 1,aaa 0;cin >> a; while (aa<a) aaa aa, aa 2;cout << aaa;i…...
设置IDEA的内存大小,让IDEA更流畅: 建议设置在 2048 MB 及以上
文章目录 引言I 更改内存设置基于窗口界面进行内存设置修改内存配置文件II IDEA中的一些常见问题及其解决方案引言 方式一:基于窗口界面进行内存设置方式二:修改内存配置文件I 更改内存设置 基于窗口界面进行内存设置 打开IDEA,上方菜单栏 Help > Change Memory Settin…...
Ranger Hive Service连接测试失败问题解决
个人博客地址:Ranger Hive Service连接测试失败问题解决 | 一张假钞的真实世界 异常信息如下: org.apache.ranger.plugin.client.HadoopException: Unable to connect to Hive Thrift Server instance.. Unable to connect to Hive Thrift Server inst…...
车机音频参数下发流程
比如以audioControlWrapper.setParametersToAmp(keyPairValues); 下发banlance为例,链路如下 hal层 1. AudioControl.cpp hardware\interfaces\automotive\audiocontrol\aidl\default\AudioControl.cpp ndk::ScopedAStatus AudioControl::setParametersToAmp(co…...
大模型推理——MLA实现方案
1.整体流程 先上一张图来整体理解下MLA的计算过程 2.实现代码 import math import torch import torch.nn as nn# rms归一化 class RMSNorm(nn.Module):""""""def __init__(self, hidden_size, eps1e-6):super().__init__()self.weight nn.Pa…...
redis之GEO 模块
文章目录 背景GeoHash 算法redis中的GeoHash 算法基本使用增加距离获取元素位置获取元素的 hash 值附近的元素 注意事项原理 背景 如果我们有需求需要存储地理坐标,为了满足高性能的矩形区域算法,数据表需要在经纬度坐标加上双向复合索引 (x, y)&#x…...
21.2.7 综合示例
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 【例 21.7】【项目:code21-007】填充职员表并打印。 本例使用到的Excel文件为:职员信息登记表.xlsx&#x…...
使用Docker + Ollama在Ubuntu中部署deepseek
1、安装docker 这里建议用docker来部署,方便简单 安装教程需要自己找详细的,会用到跳过 如果你没有安装 Docker,可以按照以下步骤安装: sudo apt update sudo apt install apt-transport-https ca-certificates curl software-p…...
【C语言标准库函数】三角函数
目录 一、头文件 二、函数简介 2.1. 正弦函数:sin(double angle) 2.2. 余弦函数:cos(double angle) 2.3. 正切函数:tan(double angle) 2.4. 反正弦函数:asin(double value) 2.5. 反余弦函数:acos(double value)…...
CNN-day9-经典神经网络ResNet
day10-经典神经网络ResNet 1 梯度消失问题 深层网络有个梯度消失问题:模型变深时,其错误率反而会提升,该问题非过拟合引起,主要是因为梯度消失而导致参数难以学习和更新。 2 网络创新 2015年何凯明等人提出deep residual netw…...
淘宝分类详情数据获取:Python爬虫的高效实现
在电商领域,淘宝作为中国最大的电商平台之一,其分类详情数据对于市场分析、竞争对手研究以及电商运营优化具有不可估量的价值。通过Python爬虫技术,我们可以高效地获取这些数据,为电商从业者提供强大的数据支持。 一、为什么选择…...
机器学习 —— 深入剖析线性回归模型
一、线性回归模型简介 线性回归是机器学习中最为基础的模型之一,主要用于解决回归问题,即预测一个连续的数值。其核心思想是构建线性方程,描述自变量(特征)和因变量(目标值)之间的关系。简单来…...
33.日常算法
1.螺旋矩阵 题目来源 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 示例 1: 输入:matrix [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,2,3,6,9,8,7,4,5] class Solution { public:vec…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...
消防一体化安全管控平台:构建消防“一张图”和APP统一管理
在城市的某个角落,一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延,滚滚浓烟弥漫开来,周围群众的生命财产安全受到严重威胁。就在这千钧一发之际,消防救援队伍迅速行动,而豪越科技消防一体化安全管控平台构建的消防“…...
嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)
目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 编辑编辑 UDP的特征 socke函数 bind函数 recvfrom函数(接收函数) sendto函数(发送函数) 五、网络编程之 UDP 用…...
云安全与网络安全:核心区别与协同作用解析
在数字化转型的浪潮中,云安全与网络安全作为信息安全的两大支柱,常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异,并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全:聚焦于保…...
DAY 26 函数专题1
函数定义与参数知识点回顾:1. 函数的定义2. 变量作用域:局部变量和全局变量3. 函数的参数类型:位置参数、默认参数、不定参数4. 传递参数的手段:关键词参数5 题目1:计算圆的面积 任务: 编写一…...
