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

CVE-2021-28169源码分析与漏洞复现(Jetty信息泄露)

漏洞概述

漏洞名称:Jetty ConcatServlet 多重解码导致 WEB-INF 敏感信息泄露
漏洞编号:CVE-2021-28169
CVSS 评分:7.5
影响版本

  • Jetty 9.4.0 - 9.4.39
  • Jetty 10.0.0 - 10.0.1
  • Jetty 11.0.0 - 11.0.1
    修复版本
  • Jetty ≥ 9.4.40
  • Jetty ≥ 10.0.2
  • Jetty ≥ 11.0.2
    漏洞类型:路径遍历/信息泄露

CVE-2021-28169 是 Eclipse Jetty 的 Servlets 组件ConcatServletWelcomeFilter)中的安全漏洞。当开发者主动使用这些组件时,攻击者通过构造双重URL编码的路径(如 /%2557EB-INF/web.xml),利用多重解码逻辑缺陷绕过路径安全校验,直接访问 WEB-INFMETA-INF 目录下的敏感文件(如 web.xmlclasses 等),导致应用配置、源码和凭证信息泄露。


技术细节与源码分析

漏洞成因
  • 多重解码缺陷
    ConcatServlet 在处理请求参数时执行多次 URL 解码:
    1. 容器层自动解码(如 %25%
    2. ConcatServlet 自身再次解码(如 %57W
  • 安全校验滞后:路径校验在首次解码后执行,未考虑二次解码结果。
关键源码分析

(1)请求处理入口ConcatServlet.doGet()
代码定位org.eclipse.jetty.servlets.ConcatServlet#doGet

   protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String query = request.getQueryString();//  获取原始查询字符串(未解码)if (query == null) {response.sendError(204);return;} List<RequestDispatcher> dispatchers = new ArrayList<>();String[] parts = query.split("\\&");String type = null;for (String part : parts) {String path = URIUtil.canonicalPath(URIUtil.decodePath(part));// 漏洞点:第一次解码if (path == null) {response.sendError(404);return;} // 安全校验(易被绕过)if (startsWith(path, "/WEB-INF/") || startsWith(path, "/META-INF/")) {//response.sendError(404);return;} String t = getServletContext().getMimeType(path);if (t != null){if (type == null) {type = t;}else if (!type.equals(t)) {response.sendError(415);return;} }RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(path);if (dispatcher != null) {dispatchers.add(dispatcher);}} if (type != null) {response.setContentType(type);}for (RequestDispatcher dispatcher : dispatchers){//容器自动二次解码dispatcher.include((ServletRequest)request, (ServletResponse)response);}}
String path = URIUtil.canonicalPath(URIUtil.decodePath(part));

问题分析

  1. URIUtil.decodePath(part):对参数执行首次 URL 解码(如 %2557%57
  2. URIUtil.canonicalPath():路径规范化(但无法处理编码字符)
  3. 容器自动二次解码:当 RequestDispatcher 处理路径时,对 %57 再次解码为 W

安全校验缺陷

if (startsWith(path, "/WEB-INF/") || ... )  

问题分析

  • 校验时路径为首次解码结果(如 /%57EB-INF/web.xml
  • 未匹配 /WEB-INF/ 规则 → 错误放行
  • 未考虑二次解码后的真实路径(/WEB-INF/web.xml

漏洞利用原理

攻击请求

GET /static?/%2557EB-INF/web.xml HTTP/1.1

解码流程

步骤操作路径变化安全校验结果
1. 容器自动解码%2557%57/%57EB-INF/web.xml绕过(不匹配 /WEB-INF
2. URIUtil.decodePath()%57W/WEB-INF/web.xml未校验
3. RequestDispatcher实际访问文件/WEB-INF/web.xml敏感文件泄露

漏洞复现

环境搭建
1.使用 Vulhub 环境启动漏洞靶机
 docker-compose up -d 

在这里插入图片描述

2.访问访问 http://target:8080,确认服务正常运行

在这里插入图片描述

攻击步骤
1.正常通过/static?/WEB-INF/web.xml无法访问到敏感文件web.xml:

在这里插入图片描述

2.对字母W进行双URL编码,即可绕过限制访问web.xml:
http://your-ip:8080/static?/%2557EB-INF/web.xml

在这里插入图片描述


修复方案

方案1:移除二次解码(官方修复)
// 修改前(漏洞代码)
String path = URIUtil.canonicalPath(URIUtil.decodePath(part));// 修改后(修复代码)
String path = URIUtil.canonicalPath(part); // 仅规范化,不额外解码

修复效果

  • 保持路径为单次解码状态(如 /%57EB-INF
  • 安全校验可正确拦截非常规路径
方案2:增强安全校验
// 增加双重解码后校验
String decodedPath = URIUtil.decodePath(URIUtil.decodePath(part));
String canonicalPath = URIUtil.canonicalPath(decodedPath);if (startsWith(canonicalPath, "/WEB-INF/") || startsWith(canonicalPath, "/META-INF/")) {response.sendError(404);return;
}

优势:兼容旧版,但性能较低

方案3:输入过滤
// 拦截包含双重编码的请求
if (part.contains("%25")) { // 检测 % 的编码形式 %25response.sendError(400, "Malicious path detected");return;
}

修复验证对比
请求修复前结果修复后结果
/?/css/style.css正常返回正常返回
/?/%57EB-INF/web.xml绕过校验,文件泄露拦截(路径未规范化)
/?/%2557EB-INF/web.xml文件泄露拦截(检测到 %25

漏洞启示

  1. 解码一致性原则:各层组件应统一解码策略,避免多重解码产生语义差异。
  2. 深度防御实践:敏感目录访问需在解码后、规范化后、业务逻辑前多层校验。
  3. 组件最小化:未使用的功能组件(如 ConcatServlet)应及时禁用。

参考链接

  1. CVE-2021-28169 官方通告(GitHub Advisory)
  2. Vulhub 漏洞复现环境指南
  3. 企业级防御实践(Tenable 报告)

附:多重解码漏洞模式对比

漏洞触发方式防护关键点
CVE-2021-28164单次编码绕过(%2e先解码后规范化
CVE-2021-28169双重编码绕过%2557避免多次解码
http://www.xdnf.cn/news/10640.html

相关文章:

  • 基于springboot的民间文化艺术品销售系统
  • 调整数据集的方法
  • 达芬奇(DaVinci Resolve)下载安装教程
  • 关闭函数闭包的理解
  • 一元函数积分
  • C++string1号
  • ps色相饱和度调整
  • ESP32与STM32
  • 回测效率提升500%!khQuant打板策略回测性能深度剖析——基于miniQMT的回测系统深度优化【AI量化第29篇】
  • 【Linux】权限chmod命令+Linux终端常用快捷键
  • 审计-函证
  • 自适应流量调度用于遥操作:面向时间敏感网络的通信与控制协同优化框架
  • 状态机实现文件单词统计
  • 基于STM32控制直流电机加减速正反转设计
  • FDR的定位原理
  • Transformer核心技术深度解析:多头注意力机制与架构精粹
  • 计算机视觉---YOLOv6
  • web架构3------(nginx的return跳转,gzip压缩,目录浏览,访问控制和location符号优先级)
  • 智慧政务标准规范介绍:构建高效、协同的政务信息体系
  • EchoMimicV2:迈向引人注目、简化的半身人类动画
  • vscode中的markdown表格列宽
  • DAY 39 超大力王爱学Python
  • ThreadLocal ,底层原理,强引用,弱引用,内存泄漏
  • Ⅲ-1.计算机二级选择题(三大结构之基本语句)
  • C++11 : 智能指针
  • FreeCAD源码分析: 单位制系统
  • 量子物理:初步认识量子物理
  • 车载软件更新 --- 数据完整性和正确性策略(数据验签事宜汇总)
  • 香橙派3B学习笔记5:Linux文件系统分区_A/B系统分区
  • C++ - 标准库之 <sstream> ostringstream(ostringstream 概述、基本使用、清空内容、进阶使用)