Jetty 9.4.37-9.4.42 路径遍历漏洞深度解析:从RFC 3986规范到3种绕过手法复现

📅 2026/7/7 17:14:13 👁️ 阅读次数 📝 编程学习
Jetty 9.4.37-9.4.42 路径遍历漏洞深度解析:从RFC 3986规范到3种绕过手法复现

Jetty路径遍历漏洞全解析:从RFC 3986规范到实战绕过技巧

在Java Web开发领域,Jetty作为轻量级高性能的Servlet容器和HTTP服务器,凭借其模块化设计和嵌入式特性广受开发者青睐。然而2021年曝光的CVE-2021-28164和CVE-2021-34429漏洞却揭示了其在URI规范化处理中的深层安全隐患。本文将带您深入剖析漏洞背后的RFC规范原理,并通过三种独特绕过手法还原攻击全貌。

1. 漏洞背景与RFC 3986规范解读

RFC 3986作为统一资源标识符(URI)的通用语法标准,其第5.2.4节明确定义了点段(dot segments)的处理规则。所谓点段特指路径中的.(当前目录)和..(父目录)符号,规范要求这些符号必须在解析过程中被移除,仅保留其代表的层次关系。

Jetty 9.4.37为实现RFC合规性引入新的URI规范化逻辑时,开发者做出了一个关键假设:URI中的路径分隔符(/)必须显式存在才能进行路径遍历检测。这个看似合理的假设却埋下了严重的安全隐患。

关键点:RFC规范要求URI解析器必须处理以下形式的路径:

  • /a/b/.//a/b/
  • /a/b/..//a/
  • /%2e//.//

实际测试表明,当访问http://vuln-server/%2e/WEB-INF/web.xml时:

  1. Jetty首先对%2e进行URL解码得到/.
  2. 规范化逻辑错误地保留了该路径
  3. 最终成功访问到受保护的WEB-INF目录

2. 漏洞利用的三重奏:绕过手法详解

2.1 Unicode编码绕过(%u002e)

Unicode编码提供了一种精妙的绕过方式。%u002e.字符的Unicode表示,这种编码形式在Jetty的早期处理阶段会被特殊对待:

GET /%u002e/WEB-INF/web.xml HTTP/1.1 Host: vuln-server:8080

处理流程对比

处理阶段正常请求恶意请求
初始URI/WEB-INF/web.xml/%u002e/WEB-INF/web.xml
URL解码-/.//WEB-INF/web.xml
规范化阻断访问错误保留路径
结果返回403/404返回200 OK

2.2 空字节截断(.%00)

空字节(%00)在多种编程语言中具有特殊含义,常被用作字符串终止符。Jetty在处理包含空字节的路径时会出现解析歧义:

curl -v http://vuln-server/.%00/WEB-INF/web.xml

技术细节

  • 空字节导致规范化过程提前终止
  • 安全检查逻辑被部分绕过
  • 文件系统API处理时忽略空字节后的内容

2.3 双重编码技巧(%252e)

通过二次编码%字符本身(%25),可以构造更隐蔽的攻击向量:

原始:. 一次编码:%2e 二次编码:%252e

这种手法能有效规避某些WAF设备的检测,因为多数安全设备只进行单层URL解码。

3. 漏洞复现环境搭建

使用Docker快速搭建漏洞测试环境:

FROM jetty:9.4.40 COPY webapp /var/lib/jetty/webapps/ROOT EXPOSE 8080

关键配置项

  • jetty.httpConfig.uriCompliance=RFC3986
  • jetty.servlet.checkOtherSessions=false

启动命令:

docker build -t jetty-vuln . docker run -p 8080:8080 jetty-vuln

4. 防御方案与最佳实践

4.1 官方修复方案对比

版本修复措施有效性
9.4.39增强UriCompliance检查部分有效
9.4.43引入DenyUrlEncodedSlashRule完全修复
10.0.0重构URI解析引擎根治问题

4.2 临时缓解措施

对于无法立即升级的系统,建议配置:

<Configure class="org.eclipse.jetty.server.HttpConfiguration"> <Call name="addCustomizer"> <Arg> <New class="org.eclipse.jetty.server.ForwardedRequestCustomizer"/> </Arg> </Call> <Set name="uriCompliance">LEGACY</Set> </Configure>

4.3 深度防御策略

  1. 输入验证

    public static boolean isSafePath(String path) { return !path.contains("..") && !path.contains("%2e") && !path.contains("%252e"); }
  2. 权限控制矩阵

    资源类型默认权限建议权限
    WEB-INF禁止访问400 Bad Request
    META-INF禁止访问403 Forbidden
    JSP文件仅执行拒绝直接访问
  3. WAF规则示例

    location ~* "/(WEB-INF|META-INF)/" { deny all; return 403; } location ~* "(%u002e|%2e|%252e)" { deny all; return 400; }

5. 漏洞挖掘方法论延伸

从Jetty漏洞中可以提炼出通用的安全审计方法:

  1. 规范对比测试

    • 对比RFC标准与实现代码的差异点
    • 特别关注边界条件处理
  2. 编码变异测试

    • 测试所有已知的编码形式(UTF-8、URL编码、Unicode等)
    • 尝试混合使用多种编码方式
  3. 解析器一致性检查

    def test_parser_consistency(parser): cases = ["/a/b/../", "/a/b/%2e%2e/", "/a/b/..%00/"] for case in cases: if parser(case) != "/a/": raise VulnerabilityFound(case)

在实战中发现,许多中间件漏洞都源于规范实现的不完整性。安全研究人员应当培养"规范驱动测试"的思维模式,从标准文档中寻找可能被误解或忽略的细节要求。