Jetty 9.4.37-9.4.42 路径遍历漏洞深度解析:3种绕过手法与修复方案对比

Jetty 9.4.37-9.4.42 路径遍历漏洞深度解析:3种绕过手法与修复方案对比 Jetty路径遍历漏洞全解析从RFC 3986规范到实战绕过技巧在Java Web生态中Jetty作为轻量级高性能的Servlet容器被广泛应用于微服务架构和云原生环境。然而其9.4.37至9.4.42版本存在的路径遍历漏洞CVE-2021-28164及其绕过漏洞CVE-2021-34429却暴露出URI解析机制与安全防护之间的深刻矛盾。本文将带您深入漏洞形成机理拆解三种精妙绕过手法并提供可落地的修复方案比对。1. 漏洞背景与影响范围Jetty作为Eclipse基金会旗下的开源项目以其模块化设计和嵌入式特性著称。在9.4.37版本中为符合RFC 3986规范对URI路径解析的要求开发团队对.和..的处理逻辑进行了调整却意外打开了潘多拉魔盒。受影响版本矩阵版本分支受影响版本范围修复版本Jetty 9.x9.4.37 ≤ version ≤ 9.4.429.4.39 / 9.4.43Jetty 10.x10.0.1 ≤ version ≤ 10.0.510.0.6Jetty 11.x11.0.1 ≤ version ≤ 11.0.511.0.6漏洞本质是规范化路径解析缺陷攻击者通过精心构造的URI可绕过安全限制直接访问WEB-INF目录下的敏感文件如web.xml、classes目录等。根据GitHub安全团队的统计截至2023年Q2仍有12%的Jetty部署存在未修复的路径遍历风险。2. 漏洞形成机理深度分析2.1 RFC 3986规范与Jetty实现的冲突RFC 3986第5.2.4节明确规定.和..被称为点段用于路径层次结构的相对引用。与文件系统不同这些点段仅在URI路径中解释层次结构并应在解析过程中被移除。Jetty为实现该规范在org.eclipse.jetty.http.PathMap类中添加了路径规范化逻辑。关键处理流程如下public static String normalizePath(String path) { // 处理连续的斜杠 path path.replaceAll(/, /); // 处理点段 String[] segments path.split(/); LinkedListString stack new LinkedList(); for (String seg : segments) { if (seg.equals(..)) { if (!stack.isEmpty()) stack.removeLast(); } else if (!seg.equals(.) !seg.isEmpty()) { stack.add(seg); } } return / String.join(/, stack); }这种实现存在两个致命缺陷编码字符处理不当未对URL编码字符进行先解码后验证空字节截断问题未正确处理%00等特殊字符2.2 安全防护的薄弱环节Jetty的防护机制存在三处关键失误验证顺序错误graph LR A[接收请求] -- B[URL解码] B -- C[路径规范化] C -- D[安全检查]正确的顺序应该是graph LR A[接收请求] -- B[初步过滤] B -- C[URL解码] C -- D[路径规范化] D -- E[最终安全检查]多重解析不一致Web容器层与Servlet API层对路径的解析存在差异默认合规模式过于宽松未对特殊编码字符实施严格限制3. 三种绕过手法实战解析3.1 Unicode编码绕过%u002e攻击原理%u002e是.的Unicode编码形式Jetty在路径规范化前未进行Unicode解码利用步骤构造恶意URLhttp://target/%u002e/WEB-INF/web.xml服务器接收后首次路径检查/%u002e/WEB-INF/web.xml不识别为点段实际访问路径/./WEB-INF/web.xml解析后等效防御难点需同时拦截所有点段的编码形式如%2e、%u002e等可能影响合法的Unicode字符使用3.2 空字节截断.%00攻击原理利用Java处理空字节的特性%00导致路径规范化提前终止利用过程GET /.%00/WEB-INF/web.xml HTTP/1.1 Host: vulnerable-app关键日志特征[WARN] org.eclipse.jetty.server.HttpChannel - /WEB-INF/web.xml3.3 混合路径遍历a/b/..%00/最隐蔽的攻击方式构造看似合法的路径/static/../..%00/WEB-INF/web.xml分步解析规范化前static/..被处理返回上级目录%00截断后续安全检查效果对比请求路径规范化结果是否阻断/a/b/../../WEB-INF/web.xml/WEB-INF/web.xml是/a/b/..%00/WEB-INF/web.xml/a/WEB-INF/web.xml否4. 修复方案横向对比4.1 官方补丁分析9.4.39版本修复// 新增编码检查 if (path.contains(%2e) || path.contains(%2E)) { throw new IllegalStateException(Invalid path); } // 强化规范化逻辑 path URIUtil.canonicalPath(path);9.4.43版本增强引入严格的Unicode解码前校验增加空字节检测机制默认启用org.eclipse.jetty.http.HttpCompliance.RFC7230模式4.2 临时缓解措施对于无法立即升级的环境自定义过滤器public class PathTraversalFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { String path ((HttpServletRequest)req).getRequestURI(); if (path.matches(.*(%u002e|%2e|%00).*)) { ((HttpServletResponse)res).sendError(403); return; } chain.doFilter(req, res); } }配置调整# jetty.xml 配置片段 Call nameaddBean Arg New classorg.eclipse.jetty.server.handler.ContextHandler Set namecontextPath//Set Set nameprotectedTargets Array typeString Item/WEB-INF/Item Item/META-INF/Item /Array /Set /New /Arg /Call4.3 修复方案评估表方案类型实施难度防护效果性能影响适用场景升级至9.4.43低★★★★★无新部署环境自定义过滤器中★★★☆☆5%临时应急反向代理过滤高★★★★☆10-15%无法修改应用代码权限最小化配置中★★☆☆☆无配合其他方案使用5. 防御体系构建建议纵深防御策略输入验证层在负载均衡器/Nginx上过滤异常路径location ~* (%u002e|%2e|%00) { return 403; }运行时防护启用Java Security Manager配置自定义Policy文件监控与响应# 日志监控规则示例 grep -E (/WEB-INF|%u002e|%00) /var/log/jetty/access.log架构优化将静态资源与敏感配置分离部署使用Seccomp等容器安全机制在云原生环境下建议结合服务网格如Istio实施全局安全策略apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: jetty-pathguard spec: rules: - to: - operation: paths: [/*] when: - key: request.headers[uri] notValues: [*%u002e*, *%00*]通过本文的深度剖析我们不仅理解了Jetty路径遍历漏洞的技术本质更掌握了从攻击者视角审视系统安全性的方法。这种双向思维正是构建真正有效防御体系的关键所在。