CVE-2020-1957 Shiro 权限绕过漏洞在 SpringBoot 高版本下的表现
字数 2034 2025-08-11 08:36:18

Apache Shiro 权限绕过漏洞(CVE-2020-1957)深度分析

漏洞概述

CVE-2020-1957是Apache Shiro框架中的一个权限绕过漏洞,主要由于Shiro与Spring框架对URI路径处理方式存在差异导致。攻击者可以通过构造特殊路径绕过Shiro的权限控制,访问受保护的资源。

漏洞影响版本

  • Shiro < 1.5.0

漏洞原理分析

路径处理差异

在Spring框架中:

  • /drunkbaby/xx/drunkbaby/xx/ 会被处理成相同的路径 /drunkbaby/xx

而在Shiro中:

  • /drunkbaby/xx/drunkbaby/xx/ 被视为不同的路径

这种解析差异导致攻击者可以通过在路径末尾添加/来绕过Shiro的权限校验。

关键处理流程

  1. Shiro处理阶段

    • 处理入口:org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain()
    • 关键方法:pathMatches(),该方法不会将/user/add识别为/user/add/
  2. Spring处理阶段

    • 处理入口:org.springframework.web.servlet.DispatcherServlet#doDispatch
    • 关键方法:org.springframework.web.servlet.mvc.condition.PatternsRequestCondition#getMatchingPatterns()
    • Spring会将带/的路径匹配到正确的handler

高版本SpringBoot下的特殊Bypass方式

在高版本SpringBoot中,还存在另一种绕过方式:

  • 使用分号构造路径,如/user;/add

处理流程:

  1. Shiro处理阶段:

    • 通过normalize(decodeAndCleanUriString(request, uri))处理URI
    • 使用indexOf()截取到;之前的内容,返回/user
    • /user/user/add不匹配,返回false,导致权限绕过
  2. Spring处理阶段:

    • 通过removeSemicolonContent()方法处理URI
    • 最终会正确匹配到/user/add的handler

传统Payload分析

传统Payload形式为/xxx/..;/user/add,但有以下限制:

  • 要求SpringBoot版本 < 2.3
  • 处理流程:
    • UrlPathHelper#getLookupPathForRequest
    • decodeAndCleanUriString()方法依次执行:
      1. 过滤;
      2. URL解码
      3. 过滤//
    • 最终返回/admin/index等路径,实现绕过

环境搭建

参考环境:

https://github.com/Drun1baby/JavaSecurityLearning/tree/main/JavaSecurity/Shiro/shiro682

搭建要点:

  1. 使用受影响版本的Shiro(<1.5.0)
  2. 配置SpringBoot环境
  3. 设置需要权限控制的路径

漏洞复现步骤

  1. 直接访问受保护路径(如/authc),应返回302重定向
  2. 在路径末尾添加/(如/authc/),成功绕过权限检查
  3. 或使用分号Payload(如/user;/add)绕过

调试分析

Shiro调试关键点

  • 断点位置:PathMatchingFilterChainResolver.getChain()
  • 关注getPathWithinApplication()方法处理后的URI

Spring调试关键点

  • 断点位置:DispatcherServlet.doDispatch()
  • 关注getHandlerInternal()initLookupPath()方法
  • 特别关注removeSemicolonContent()方法的处理逻辑

漏洞修复

修复方案

  1. 升级到Shiro 1.5.2及以上版本
  2. 修复方式变更:
    • 不再直接从request.getRequestUri获取URI
    • 改为获取request的ContextPath、ServletPath、PathInfo后重新拼接
    • 例如/xxx/..;/user/add会被拼接为//xxx/user/add,无法绕过

修复代码分析

修复commit主要修改了URI获取方式,确保路径处理与Spring保持一致。

总结

  1. 漏洞本质是Shiro与Spring路径解析不一致导致
  2. 主要利用方式:
    • 路径末尾添加/
    • 使用分号构造特殊路径(高版本SpringBoot)
    • 传统/xxx/..;/方式(低版本SpringBoot)
  3. 修复关键在于统一路径处理逻辑

参考资源

  1. 官方修复commit
  2. 漏洞测试环境:https://github.com/Drun1baby/JavaSecurityLearning
  3. 相关CVE分析文章
Apache Shiro 权限绕过漏洞(CVE-2020-1957)深度分析 漏洞概述 CVE-2020-1957是Apache Shiro框架中的一个权限绕过漏洞,主要由于Shiro与Spring框架对URI路径处理方式存在差异导致。攻击者可以通过构造特殊路径绕过Shiro的权限控制,访问受保护的资源。 漏洞影响版本 Shiro < 1.5.0 漏洞原理分析 路径处理差异 在Spring框架中: /drunkbaby/xx 与 /drunkbaby/xx/ 会被处理成相同的路径 /drunkbaby/xx 而在Shiro中: /drunkbaby/xx 与 /drunkbaby/xx/ 被视为不同的路径 这种解析差异导致攻击者可以通过在路径末尾添加 / 来绕过Shiro的权限校验。 关键处理流程 Shiro处理阶段 : 处理入口: org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain() 关键方法: pathMatches() ,该方法不会将 /user/add 识别为 /user/add/ Spring处理阶段 : 处理入口: org.springframework.web.servlet.DispatcherServlet#doDispatch 关键方法: org.springframework.web.servlet.mvc.condition.PatternsRequestCondition#getMatchingPatterns() Spring会将带 / 的路径匹配到正确的handler 高版本SpringBoot下的特殊Bypass方式 在高版本SpringBoot中,还存在另一种绕过方式: 使用分号构造路径,如 /user;/add 处理流程: Shiro处理阶段: 通过 normalize(decodeAndCleanUriString(request, uri)) 处理URI 使用 indexOf() 截取到 ; 之前的内容,返回 /user /user 与 /user/add 不匹配,返回false,导致权限绕过 Spring处理阶段: 通过 removeSemicolonContent() 方法处理URI 最终会正确匹配到 /user/add 的handler 传统Payload分析 传统Payload形式为 /xxx/..;/user/add ,但有以下限制: 要求SpringBoot版本 < 2.3 处理流程: UrlPathHelper#getLookupPathForRequest decodeAndCleanUriString() 方法依次执行: 过滤 ; URL解码 过滤 // 最终返回 /admin/index 等路径,实现绕过 环境搭建 参考环境: 搭建要点: 使用受影响版本的Shiro( <1.5.0) 配置SpringBoot环境 设置需要权限控制的路径 漏洞复现步骤 直接访问受保护路径(如 /authc ),应返回302重定向 在路径末尾添加 / (如 /authc/ ),成功绕过权限检查 或使用分号Payload(如 /user;/add )绕过 调试分析 Shiro调试关键点 断点位置: PathMatchingFilterChainResolver.getChain() 关注 getPathWithinApplication() 方法处理后的URI Spring调试关键点 断点位置: DispatcherServlet.doDispatch() 关注 getHandlerInternal() 和 initLookupPath() 方法 特别关注 removeSemicolonContent() 方法的处理逻辑 漏洞修复 修复方案 升级到Shiro 1.5.2及以上版本 修复方式变更: 不再直接从 request.getRequestUri 获取URI 改为获取request的ContextPath、ServletPath、PathInfo后重新拼接 例如 /xxx/..;/user/add 会被拼接为 //xxx/user/add ,无法绕过 修复代码分析 修复commit主要修改了URI获取方式,确保路径处理与Spring保持一致。 总结 漏洞本质是Shiro与Spring路径解析不一致导致 主要利用方式: 路径末尾添加 / 使用分号构造特殊路径(高版本SpringBoot) 传统 /xxx/..;/ 方式(低版本SpringBoot) 修复关键在于统一路径处理逻辑 参考资源 官方修复commit 漏洞测试环境:https://github.com/Drun1baby/JavaSecurityLearning 相关CVE分析文章