Shiro < 1.11.0 & Spring Boot 2.6+ 鉴权绕过(CVE-2023-22602)
字数 2171 2025-08-06 18:08:11

Shiro < 1.11.0 & Spring Boot 2.6+ 鉴权绕过漏洞分析(CVE-2023-22602)

漏洞概述

在Shiro 1.11.0版本之前,当与Spring Boot 2.6以上版本组合使用时,在默认配置下,配合特定的路由规则,攻击者可以通过发送特殊的请求造成Shiro中的鉴权绕过。

环境搭建

  1. 获取标准Spring+Shiro项目(可使用Shiro的samples)
  2. 修改pom.xml添加日志依赖:
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.20</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.5.6</version>
</dependency>
  1. 在application.properties中添加:
debug=true
trace=true
  1. 创建logback.xml配置文件:
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder><pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern></encoder>
    </appender>
    <logger name="org.apache.shiro" level="ALL" additivity="false">
        <appender-ref ref="STDOUT"/>
    </logger>
    <root level="ALL">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

请求处理流程分析

Spring初始化流程

  1. 请求进入后,首先通过ApplicationFilterChain.doFilter处理
  2. 执行顺序:
    • CharacterEncodingFilter
    • FormContentFilter
    • RequestContextFilter
    • ShiroFilter

Shiro处理流程

  1. 进入ShiroFilter后关键调用过程:

    • ShiroFilter.doFilter
    • AbstractShiroFilter.doFilterInternal
    • AbstractShiroFilter.executeChain
    • PathMatchingFilterChainResolver.getChain
    • AntPathMatcher.doMatch
    • DefaultFilterChainManager.proxy
    • SimpleNamedFilterList.proxy
    • ProxiedFilterChain.doFilter
  2. Shiro会根据请求匹配对应的filters,封装成ProxiedFilterChain

Spring路由匹配

  1. 在filter链执行完成后,调用servlet.service(request, response)
  2. 关键调用:
    • HttpServlet.service
    • FrameworkServlet.service
    • FrameworkServlet.processRequest
    • DispatcherServlet.doService
    • DispatcherServlet.getHandler
    • AbstractHandlerMethodMapping.getHandlerInternal
    • AbstractHandlerMapping.initLookupPath
    • AbstractHandlerMapping.lookupHandlerMethod

路由匹配差异分析

Shiro中的路由匹配

  1. Shiro在初始化时会根据配置将路由与filter链匹配

  2. 示例配置:

    chainDefinition.addPathDefinition("/admin/**", "roles[admin]");
    
  3. URI获取:

    • 通过getPathWithinApplication(request)获取
    • WebUtils.getPathWithinApplication中的normalize会解析/.//../
    • 最终获取的是经过urldecode和路径解析后的URI
  4. 匹配方式:

    • 使用AntPathMatcher
    • 支持?(单字符)、*(单级目录)、**(多级目录)

Spring中的路由匹配

  1. Spring 2.6+默认使用path_pattern_parser模式

  2. 两种匹配模式:

    • ant_path_matcher:对应PatternsRequestCondition
    • path_pattern_parser:对应PathPatternsRequestCondition
  3. 差异:

    • ant_path_matcher

      • 获取URI:UrlPathHelper.getResolvedLookupPath(request)
      • 使用Shiro的ShiroUrlPathHelper.getPathWithinApplication
      • 结果与Shiro一致(解析..
    • path_pattern_parser

      • 获取URI:ServletRequestPathUtils.getParsedRequestPath(request).pathWithinApplication()
      • 获取原始URI(不解析..

漏洞利用

利用条件

  1. Spring使用path_pattern_parser配置(2.6+默认)
  2. Shiro配置多级路径规则(如/admin/**
  3. Controller使用多级路径匹配(如@RequestMapping("/admin/**")

示例利用

发送请求:

GET /admin/.. HTTP/1.1
  1. Shiro处理:

    • 解析URI为/(解析了..
    • 不匹配/admin/**规则
    • 鉴权通过
  2. Spring处理:

    • 不解析..
    • 匹配/admin/**规则
    • 路由到受保护接口

受影响的路由配置

以下Controller配置可能被绕过:

@RequestMapping("/admin/**")
@RequestMapping("/admin/*")
@RequestMapping("/admin/{*path}")

以下配置不受影响:

@RequestMapping("/admin")

漏洞修复

  1. Shiro 1.11.0中强制使用ant_path_matcher模式
  2. 升级Shiro到1.11.0或更高版本

防御建议

  1. 及时升级Shiro到安全版本
  2. 避免在Controller中使用多级通配符路径
  3. 考虑使用注解方式进行权限控制(如@RequiresRoles
  4. 统一应用和框架的路由解析方式
Shiro < 1.11.0 & Spring Boot 2.6+ 鉴权绕过漏洞分析(CVE-2023-22602) 漏洞概述 在Shiro 1.11.0版本之前,当与Spring Boot 2.6以上版本组合使用时,在默认配置下,配合特定的路由规则,攻击者可以通过发送特殊的请求造成Shiro中的鉴权绕过。 环境搭建 获取标准Spring+Shiro项目(可使用Shiro的samples) 修改pom.xml添加日志依赖: 在application.properties中添加: 创建logback.xml配置文件: 请求处理流程分析 Spring初始化流程 请求进入后,首先通过 ApplicationFilterChain.doFilter 处理 执行顺序: CharacterEncodingFilter FormContentFilter RequestContextFilter ShiroFilter Shiro处理流程 进入ShiroFilter后关键调用过程: ShiroFilter.doFilter AbstractShiroFilter.doFilterInternal AbstractShiroFilter.executeChain PathMatchingFilterChainResolver.getChain AntPathMatcher.doMatch DefaultFilterChainManager.proxy SimpleNamedFilterList.proxy ProxiedFilterChain.doFilter Shiro会根据请求匹配对应的filters,封装成 ProxiedFilterChain Spring路由匹配 在filter链执行完成后,调用 servlet.service(request, response) 关键调用: HttpServlet.service FrameworkServlet.service FrameworkServlet.processRequest DispatcherServlet.doService DispatcherServlet.getHandler AbstractHandlerMethodMapping.getHandlerInternal AbstractHandlerMapping.initLookupPath AbstractHandlerMapping.lookupHandlerMethod 路由匹配差异分析 Shiro中的路由匹配 Shiro在初始化时会根据配置将路由与filter链匹配 示例配置: URI获取: 通过 getPathWithinApplication(request) 获取 WebUtils.getPathWithinApplication 中的 normalize 会解析 /./ 和 /../ 最终获取的是经过urldecode和路径解析后的URI 匹配方式: 使用 AntPathMatcher 支持 ? (单字符)、 * (单级目录)、 ** (多级目录) Spring中的路由匹配 Spring 2.6+默认使用 path_pattern_parser 模式 两种匹配模式: ant_path_matcher :对应 PatternsRequestCondition path_pattern_parser :对应 PathPatternsRequestCondition 差异: ant_path_matcher : 获取URI: UrlPathHelper.getResolvedLookupPath(request) 使用Shiro的 ShiroUrlPathHelper.getPathWithinApplication 结果与Shiro一致(解析 .. ) path_pattern_parser : 获取URI: ServletRequestPathUtils.getParsedRequestPath(request).pathWithinApplication() 获取原始URI(不解析 .. ) 漏洞利用 利用条件 Spring使用 path_pattern_parser 配置(2.6+默认) Shiro配置多级路径规则(如 /admin/** ) Controller使用多级路径匹配(如 @RequestMapping("/admin/**") ) 示例利用 发送请求: Shiro处理: 解析URI为 / (解析了 .. ) 不匹配 /admin/** 规则 鉴权通过 Spring处理: 不解析 .. 匹配 /admin/** 规则 路由到受保护接口 受影响的路由配置 以下Controller配置可能被绕过: 以下配置不受影响: 漏洞修复 Shiro 1.11.0中强制使用 ant_path_matcher 模式 升级Shiro到1.11.0或更高版本 防御建议 及时升级Shiro到安全版本 避免在Controller中使用多级通配符路径 考虑使用注解方式进行权限控制(如 @RequiresRoles ) 统一应用和框架的路由解析方式