Tomcat URL解析差异性导致的安全问题
字数 2428 2025-08-20 18:17:53

Tomcat URL解析差异性导致的安全问题分析

0x01 简介

Tomcat是常见的Web中间件,利用NIO技术处理HTTP请求。在接收到请求时会对客户端提交的参数、URL、Header和Body数据进行解析,并生成Request对象,然后调用实际的JSP或Servlet。

当后台程序使用getRequestURI()getRequestURL()函数来解析用户请求的URL时,若URL中包含特殊符号,可能造成访问限制绕过的安全风险。

0x02 URL解析差异性

HttpServletRequest中几个解析URL的函数

在Servlet处理URL请求的路径时,HTTPServletRequest有如下常用函数:

  1. request.getRequestURL():返回全路径
  2. request.getRequestURI():返回除去Host(域名或IP)部分的路径
  3. request.getContextPath():返回工程名部分,如果工程映射为/,则返回为空
  4. request.getServletPath():返回除去Host和工程名部分的路径
  5. request.getPathInfo():仅返回传递到Servlet的路径,如果没有传递额外的路径信息,则返回Null

特殊字符的URL解析

通过实验测试Tomcat对不同特殊字符的处理:

正常访问

http://localhost:8080/urltest/index.jsp - 正常输出各函数解析结果

插入 ./ 访问

http://localhost:8080/urltest/./././index.jsp - 能正常访问
http://localhost:8080/urltest/.a/.bb/.ccc/index.jsp - 返回404

插入 ../ 访问

http://localhost:8080/urltest/../index.jsp - 返回404(实际访问/index.jsp
http://localhost:8080/urltest/noexist/../index.jsp - 能正常访问

插入 ;/ 访问

http://localhost:8080/urltest/;/;/;/index.jsp - 能正常访问
http://localhost:8080/urltest/;a/;bb/;ccc/index.jsp - 能正常访问

插入其他特殊字符访问

~ ! @ # $ % ^ & * ( ) - _ = + [ ] { } \ | : ' " < > ?` - 均返回400或404

小结

Tomcat中的URL解析支持嵌入./../;xx/等特殊字符。getRequestURL()getRequestURI()这两个函数解析提取的URL内容包含嵌入的特殊字符,使用不当时会存在安全问题如绕过认证。

0x03 调试分析

Tomcat对URL特殊字符的处理

Tomcat在CoyoteAdapter.service()函数中对请求URL进行解析处理,主要调用两个关键函数:

  1. parsePathParameters()函数:

    • 寻找URL中的;
    • ;xxx/中的分号与斜杠之间的字符串以及分号本身都去掉
    • 处理示例:http://localhost:8080/urltest/;mi1k7ea/index.jsp
  2. normalize()函数:

    • \替换为/
    • 删除连续的/只保留一个
    • 删除/./
    • /../进行跨目录拼接处理
    • 返回处理后的URL路径

各解析函数的处理细节

  1. getRequestURI()

    • 直接返回请求的URL内容,不做任何处理及URL解码
  2. getRequestURL()

    • 提取协议类型、host和port
    • 调用getRequestURI()获取路径
    • 直接拼接返回,不做任何处理
  3. getServletPath()

    • 返回Tomcat处理后的MappingData类对象中的wrapperPath属性值
  4. getPathInfo()

    • 返回MappingData类对象中的pathInfo属性值
  5. getContextPath()

    • 获取Servlet上下文路径和请求目录路径
    • 处理连续的/
    • 进行工程名切分提取
    • 对切分结果进行特殊字符处理和URL解码
    • 返回处理后的路径

0x04 攻击利用

访问限制绕过场景

假设存在敏感目录/urltest/info/secret.jsp,配置了Filter进行访问控制:

public void doFilter(...) {
    String url = httpServletRequest.getRequestURI();
    if (url.startsWith("/urltest/info")) {
        httpServletResponse.getWriter().write("No Permission.");
        return;
    }
    filterChain.doFilter(servletRequest, servletResponse);
}

绕过方式

利用URL解析差异性构造以下payload可绕过限制:

  1. http://localhost:8080/urltest/./info/secret.jsp
  2. http://localhost:8080/urltest/;mi1k7ea/info/secret.jsp
  3. http://localhost:8080/urltest/mi1k7ea/../info/secret.jsp
  4. http://localhost:8080/urltest/mi1k7ea/..;/info/secret.jsp
  5. http://localhost:8080//urltest/info/secret.jsp

修复方案

使用getPathInfo()替代getRequestURI(),如Apache Shiro的修复方案所示。

0x05 参考

  1. getRequestURI()带来的安全问题
  2. Apache Shiro修复commit: https://github.com/apache/shiro/commit/3708d7907016bf2fa12691dff6ff0def1249b8ce
Tomcat URL解析差异性导致的安全问题分析 0x01 简介 Tomcat是常见的Web中间件,利用NIO技术处理HTTP请求。在接收到请求时会对客户端提交的参数、URL、Header和Body数据进行解析,并生成Request对象,然后调用实际的JSP或Servlet。 当后台程序使用 getRequestURI() 或 getRequestURL() 函数来解析用户请求的URL时,若URL中包含特殊符号,可能造成访问限制绕过的安全风险。 0x02 URL解析差异性 HttpServletRequest中几个解析URL的函数 在Servlet处理URL请求的路径时,HTTPServletRequest有如下常用函数: request.getRequestURL() :返回全路径 request.getRequestURI() :返回除去Host(域名或IP)部分的路径 request.getContextPath() :返回工程名部分,如果工程映射为/,则返回为空 request.getServletPath() :返回除去Host和工程名部分的路径 request.getPathInfo() :仅返回传递到Servlet的路径,如果没有传递额外的路径信息,则返回Null 特殊字符的URL解析 通过实验测试Tomcat对不同特殊字符的处理: 正常访问 http://localhost:8080/urltest/index.jsp - 正常输出各函数解析结果 插入 ./ 访问 http://localhost:8080/urltest/./././index.jsp - 能正常访问 http://localhost:8080/urltest/.a/.bb/.ccc/index.jsp - 返回404 插入 ../ 访问 http://localhost:8080/urltest/../index.jsp - 返回404(实际访问 /index.jsp ) http://localhost:8080/urltest/noexist/../index.jsp - 能正常访问 插入 ;/ 访问 http://localhost:8080/urltest/;/;/;/index.jsp - 能正常访问 http://localhost:8080/urltest/;a/;bb/;ccc/index.jsp - 能正常访问 插入其他特殊字符访问 ~ ! @ # $ % ^ & * ( ) - _ = + [ ] { } \ | : ' " < > ? ` - 均返回400或404 小结 Tomcat中的URL解析支持嵌入 ./ 、 ../ 、 ;xx/ 等特殊字符。 getRequestURL() 和 getRequestURI() 这两个函数解析提取的URL内容包含嵌入的特殊字符,使用不当时会存在安全问题如绕过认证。 0x03 调试分析 Tomcat对URL特殊字符的处理 Tomcat在 CoyoteAdapter.service() 函数中对请求URL进行解析处理,主要调用两个关键函数: parsePathParameters() 函数: 寻找URL中的 ; 号 将 ;xxx/ 中的分号与斜杠之间的字符串以及分号本身都去掉 处理示例: http://localhost:8080/urltest/;mi1k7ea/index.jsp normalize() 函数: 将 \ 替换为 / 删除连续的 / 只保留一个 删除 /./ 对 /../ 进行跨目录拼接处理 返回处理后的URL路径 各解析函数的处理细节 getRequestURI() : 直接返回请求的URL内容,不做任何处理及URL解码 getRequestURL() : 提取协议类型、host和port 调用 getRequestURI() 获取路径 直接拼接返回,不做任何处理 getServletPath() : 返回Tomcat处理后的 MappingData 类对象中的 wrapperPath 属性值 getPathInfo() : 返回 MappingData 类对象中的 pathInfo 属性值 getContextPath() : 获取Servlet上下文路径和请求目录路径 处理连续的 / 进行工程名切分提取 对切分结果进行特殊字符处理和URL解码 返回处理后的路径 0x04 攻击利用 访问限制绕过场景 假设存在敏感目录 /urltest/info/secret.jsp ,配置了Filter进行访问控制: 绕过方式 利用URL解析差异性构造以下payload可绕过限制: http://localhost:8080/urltest/./info/secret.jsp http://localhost:8080/urltest/;mi1k7ea/info/secret.jsp http://localhost:8080/urltest/mi1k7ea/../info/secret.jsp http://localhost:8080/urltest/mi1k7ea/..;/info/secret.jsp http://localhost:8080//urltest/info/secret.jsp 修复方案 使用 getPathInfo() 替代 getRequestURI() ,如Apache Shiro的修复方案所示。 0x05 参考 getRequestURI()带来的安全问题 Apache Shiro修复commit: https://github.com/apache/shiro/commit/3708d7907016bf2fa12691dff6ff0def1249b8ce