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

CVE-2021-34429源码分析与漏洞复现

漏洞概述

漏洞名称:Jetty 路径解析多重编码绕过漏洞
漏洞编号:CVE-2021-34429
CVSS 评分:5.3
影响版本

  • Jetty 9.4.37 - 9.4.42
  • Jetty 10.0.1 - 10.0.5
  • Jetty 11.0.1 - 11.0.5
    修复版本
  • Jetty ≥ 9.4.43
  • Jetty ≥ 10.0.6
  • Jetty ≥ 11.0.6
    漏洞类型:路径遍历/敏感信息泄露

CVE-2021-34429 是 Eclipse Jetty 服务器因 RFC 3986 合规性改造引入的路径解析逻辑缺陷。攻击者通过构造包含 Unicode 编码点段(如 %u002e)或空字符(如 %00)的恶意 URI,绕过 ContextHandler 的安全校验,直接访问 WEB-INFMETA-INF 目录下的敏感文件(如 web.xmlclasses 等),导致应用配置、数据库凭证等敏感信息泄露。
此漏洞是 CVE-2021-28164 的绕过变种,利用多重编码和空字符截断绕过修复补丁。


技术细节与源码分析

漏洞成因

Jetty 在 9.4.37 版本为符合 RFC 3986 规范,将 URI 解析顺序改为 先规范化后解码

  1. canonicalPath() 先处理明文点段./..),但忽略编码形式(如 %2e%u002e);
  2. decodePath() 后执行解码,将 %u002e 转为 .,生成有效点段路径;
  3. 安全校验滞后isProtectedTarget() 在规范化后执行,未检测解码后的真实路径。
关键源码分析

(1)路径解析入口HttpURI.parse()
代码定位org.eclipse.jetty.http.HttpURI#parse

   public void parse(String uri) {clear();this._uri = uri;parse(State.START, uri, 0, uri.length());}private void parse(State state, String uri, int offset, int end) {if (!encoded && j == 0) {if (this._param == null) {this._decodedPath = this._path;} else {this._decodedPath = this._path.substring(0, this._path.length() - this._param.length() - 1);} } else if (this._path != null) {String canonical = URIUtil.canonicalPath(this._path);// 先规范化路径(未解码)if (canonical == null)throw new BadMessageException("Bad URI"); this._decodedPath = URIUtil.decodePath(canonical);// 再解码URL编码} }

漏洞点canonicalPath() 仅过滤明文 ./..,无法识别 %u002e(Unicode 编码点)。

(2)路径规范化函数canonicalPath()
代码定位org.eclipse.jetty.http.HttpURI#canonicalPath

   public static String canonicalPath(String path) {if (path == null || path.isEmpty()) {return path;}int end = path.length();int i = 0;int dots = 0;while (i < end) {char c = path.charAt(i);switch (c) {case '/':dots = 0;break;case '.':if (dots == 0) {dots = 1;break;} dots = -1;break;default:dots = -1;break;} i++;} if (i == end) {return path;}StringBuilder canonical = new StringBuilder(path.length());canonical.append(path, 0, i);i++;while (i <= end) {       char c = (i < end) ? path.charAt(i) : Character.MIN_VALUE;switch (c) {case '\000':if (dots == 2) {if (canonical.length() < 2)return null; canonical.setLength(canonical.length() - 1);canonical.setLength(canonical.lastIndexOf("/") + 1);} break;case '/':switch (dots) {case 1:break;case 2:if (canonical.length() < 2)return null; canonical.setLength(canonical.length() - 1);canonical.setLength(canonical.lastIndexOf("/") + 1);break;default:canonical.append(c); break;} dots = 0;break;case '.':switch (dots) {case 0:dots = 1;break;case 1:dots = 2;break;case 2:canonical.append("...");dots = -1;break;} canonical.append('.');break;         default:switch (dots) {        case 1:canonical.append('.');break;case 2:canonical.append("..");break;}           canonical.append(c);dots = -1;break;} i++;} return canonical.toString();// 仅处理明文"."和"..",忽略%2e等编码形式}

缺陷:输入 /%u002e/WEB-INF/web.xml 经此函数后路径不变,因 %u002e 未被识别为点段。

(3)安全校验逻辑ContextHandler.isProtectedTarget()
代码定位org.eclipse.jetty.server.handler.ContextHandler#isProtectedTarget

   public boolean isProtectedTarget(String target) {if (target == null || this._protectedTargets == null) {return false;}while (target.startsWith("//")){target = URIUtil.compactPath(target);}     for (int i = 0; i < this._protectedTargets.length; i++) {       String t = this._protectedTargets[i];if (StringUtil.startsWithIgnoreCase(target, t)) {   // 直接匹配路径保护路径前缀       if (target.length() == t.length()) {return true;} char c = target.charAt(t.length());if (c == '/' || c == '?' || c == '#' || c == ';')return true; } } return false;}

绕过原理:校验时 target/%u002e/WEB-INF/web.xml,不匹配 /WEB-INF 前缀,但解码后实际路径为 ./WEB-INF/web.xml


漏洞复现

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

在这里插入图片描述

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

在这里插入图片描述

攻击步骤
1.直接访问/WEB-INF/web.xml将会返回404页面

在这里插入图片描述

2.使用/%u002e/WEB-INF/web.xml来绕过限制下载web.xml:
其他利用 Payload
Payload技术原理
/.%00/WEB-INF/web.xml空字符截断规范化逻辑
/a/b/..%00/WEB-INF/web.xml路径遍历 + 空字符组合绕过
实际影响
  • 敏感信息泄露web.xml(数据库密码)、classes/(业务逻辑源码);
  • 攻击成本低:无需认证,仅需构造 URL;
  • 横向渗透基础:泄露的配置可能暴露内网接口或密钥。

修复方案

官方修复(Jetty ≥ 9.4.43)

补丁核心调整路径处理顺序 + 增强校验

  1. 先解码后规范化
    // HttpURI.parse() 修改后  
    _decodedPath = decodePath(rawURI);  
    _path = canonicalPath(_decodedPath); // 先解码后规范化  
    
  2. 拒绝危险字符:检测编码点段(%u002e)、空字符(%00),直接返回 400 Bad Request。
临时缓解措施
  1. 重写规则拦截jetty.xml):
    <Call name="addRule">  <Arg>  <New class="org.eclipse.jetty.rewrite.handler.RewriteRegexRule">  <Set name="regex">.*/(?:\.+/)+.*</Set>  <Set name="replacement">/WEB-INF/Not-Found</Set>  </New>  </Arg>  
    </Call>  
    
    作用:将含编码点段的请求重定向至无效路径。
  2. 权限控制:确保 WEB-INF 目录权限禁止非授权访问。

漏洞启示与防御框架

路径解析漏洞防御模型
用户请求
输入过滤
统一解码
规范化处理
安全校验
资源访问

最佳实践

  1. 输入过滤层:拦截含 %u002e%00 的请求;
  2. 解码规范化层:强制先解码后规范化;
  3. 业务校验层:对比规范化前后路径一致性。

附:Jetty 路径漏洞修复史

漏洞绕过方式修复版本修复核心
CVE-2021-28164%2e 编码点段≥ 9.4.39先解码后规范化
CVE-2021-28169双重编码(%2557≥ 9.4.40禁用二次解码
CVE-2021-34429Unicode 编码≥ 9.4.43拒绝危险字符

参考链接

  1. CVE-2021-34429 官方通告(Eclipse Jetty)
  2. 漏洞原理与源码分析(阿里云先知社区)

相关文章:

  • CCF CSP 第37次(2025.03)(3_模板展开_C++)(哈希表+stringstream)
  • Python数据可视化科技图表绘制系列教程(一)
  • 基于Python学习《Head First设计模式》第五章 单件模式
  • Docker部署与应用、指令
  • Qwen与Llama分词器核心差异解析
  • vue3学习
  • C++和C#界面开发方式的全面对比
  • 秋招Day12 - 计算机网络 - IP
  • 相机--相机成像原理和基础概念
  • 基于springboot的图书管理系统的设计与实现
  • Hadoop复习(九)
  • torch.distributed.launch 、 torchrun 和 torch.distributed.run 无法与 nohup 兼容
  • 如何制定数字化转型策略:从理念到落地的全面指南
  • 消费者行为变革下开源AI智能名片与链动2+1模式S2B2C商城小程序的协同创新路径
  • websocket协议
  • 互联网历史01
  • 阿里云为何,一个邮箱绑定了两个账号
  • 便携式雷达信号模拟器,定义复杂电磁环境模拟新标准
  • Python数据分析及可视化中常用的6个库及函数(二)
  • 关于 java:6. 反射机制
  • 如何处理脓包痘痘/关键词优化排名软件推荐
  • 用帝国cms做网站/今日头条武汉最新消息
  • 政府网站建设作用/品牌推广和营销推广
  • 做本地的分类信息网站/seo是什么缩写
  • 网站设计的公司选哪家/查关键词的排名工具
  • 一键建站模板/网络营销公司名字