Spring反射性文件下载漏洞(CVE-2020-5421)分析报告
漏洞概述
CVE-2020-5421是Spring Framework中的一个反射性文件下载(Reflective File Download, RFD)漏洞,影响以下版本:
- 5.2.0 - 5.2.8
- 5.1.0 - 5.1.17
- 5.0.0 - 5.0.18
- 4.3.0 - 4.3.28
- 以及更旧的不受支持版本
该漏洞是对CVE-2015-5211修复措施的绕过,攻击者可通过特定方式构造URL,绕过Spring的安全防护,导致恶意文件被下载执行。
漏洞背景
RFD漏洞原理
反射性文件下载(RFD)是一种攻击技术,攻击者通过构造特殊URL,诱使用户访问并下载恶意脚本文件。当用户执行下载的文件时,攻击者的恶意代码就会在用户环境中运行。
CVE-2015-5211
这是Spring Framework早期的一个RFD漏洞,其原理是滥用Spring的内容协商机制(content-negotiation)。攻击者可以通过在URL中添加特定后缀(如.bat、.cmd等),使响应内容被浏览器识别为可执行文件并下载。
示例代码:
@Controller
@RequestMapping(value = "/spring")
public class springRFD {
@RequestMapping("rfd")
@ResponseBody
public String Index(String content, HttpServletResponse response){
return content;
}
}
攻击方式:
- 正常访问:
http://x.x.x.x/spring/rfd?content=calc→ Content-Type为text/html - 添加.json后缀:
http://x.x.x.x/spring/rfd.json?content=calc→ Content-Type为application/json - 添加.bat后缀:
http://x.x.x.x/spring/rfd.bat?content=111→ 浏览器会下载rfd.bat文件
Spring针对CVE-2015-5211的修复措施是:
- 指定一个后缀白名单
- 对于白名单外的后缀文件类型,统一添加响应头:
Content-Disposition: inline;filename=f.txt - 这样下载的文件会被保存为f.txt,而不是原始请求中的后缀名
CVE-2020-5421漏洞分析
绕过原理
CVE-2020-5421利用了Spring处理jsessionid路径参数的特性。Spring会从请求URL中删除;jsessionid=字符串及其后面的内容(或下一个;之前的内容)。
同时,Spring允许URL路径中包含以;开头的字符串,例如:
http://x.x.x.x/spring/rfd?content=111http://x.x.x.x/spring/;xxx/rfd?content=111
这两个URL会得到相同的响应。
漏洞利用
结合上述特性,构造以下payload可以绕过CVE-2015-5211的防护:
http://x.x.x.x/spring/;jsessionid=/rfd.bat?content=calc
处理流程:
- Spring会删除
;jsessionid=及其后面的内容 - 导致后续防御代码无法获取真实的请求后缀文件名
- 防护措施失效,浏览器会下载rfd.bat文件
修复方案
Spring 5.2.9及更高版本已修复此漏洞。修复后,即使使用上述payload,仍会添加Content-Disposition: inline;filename=f.txt头,确保文件被保存为f.txt。
漏洞复现
环境搭建
- 使用受影响版本的Spring Framework(如5.2.8)
- 创建简单的Controller,如示例代码所示
- 部署应用并确保内容协商功能启用
测试步骤
- 尝试正常请求:
http://localhost:8080/spring/rfd?content=test - 尝试添加.bat后缀:
http://localhost:8080/spring/rfd.bat?content=calc- 观察响应头是否包含
Content-Disposition: inline;filename=f.txt
- 观察响应头是否包含
- 尝试绕过payload:
http://localhost:8080/spring/;jsessionid=/rfd.bat?content=calc- 在受影响版本中,不会添加防护头
- 在修复版本中,仍会添加防护头
防护建议
- 升级Spring Framework到安全版本(5.2.9+、5.1.18+、5.0.19+)
- 对于无法升级的环境,可考虑以下措施:
- 禁用内容协商功能
- 实现自定义拦截器检查可疑URL
- 配置Web应用防火墙(WAF)规则拦截可疑请求
- 教育用户不要随意点击下载不明来源的文件
总结
CVE-2020-5421展示了安全修复可能被绕过的典型案例。开发者在实现安全防护时需要考虑各种边界情况,特别是当多个功能特性交互时可能产生的副作用。对于防御方而言,及时更新依赖库并了解其安全修复历史至关重要。