Java-Shiro-权限绕过多漏洞分析
字数 3790 2025-08-11 08:36:20

Apache Shiro 权限绕过多漏洞分析与教学文档

0x00 前言

Apache Shiro 是一个强大且易用的 Java 安全框架,提供认证、授权、加密和会话管理等功能。本文详细分析 Shiro 框架中的多个权限绕过漏洞(CVE-2010-3863、CVE-2016-6802、CVE-2020-1957、CVE-2020-11989、CVE-2020-13933、CVE-2020-17510、CVE-2020-17523、CVE-2021-41303),从环境搭建到漏洞原理分析,再到修复方案,全面剖析 Shiro 权限绕过漏洞。

0x01 Shiro 基础与流程分析

环境搭建

实现 Shiro 使用需要三个核心模块:

  1. 创建 Realm 对象(自定义类)
  2. DefaultWebSecurityManager
  3. ShiroFilterFactoryBean

核心配置示例:

@Configuration
public class ShiroConfig {
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(defaultWebSecurityManager);
        
        // 添加Shiro内置过滤器
        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/user/add", "perms[user:add]");
        filterMap.put("/user/update", "perms[user:update]");
        filterMap.put("/user/*", "authc");
        bean.setFilterChainDefinitionMap(filterMap);
        
        bean.setLoginUrl("/toLogin");
        bean.setUnauthorizedUrl("/noauth");
        return bean;
    }
    
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        return securityManager;
    }
    
    @Bean
    public UserRealm userRealm() {
        return new UserRealm();
    }
}

Shiro 认证流程

  1. 初始化阶段

    • ShiroFilterFactoryBean 实现 FactoryBean 接口,Spring 初始化时调用 getObject() 方法
    • 创建 FilterChainManager 管理过滤链
    • 添加默认过滤器(anon、authc、perms等)
    • 应用全局属性(loginUrl、successUrl、unauthorizedUrl)
    • 加载自定义过滤器规则
  2. 请求处理阶段

    • Tomcat 收到请求后,调用 Shiro 的 OncePerRequestFilter
    • 通过 PathMatchingFilterChainResolver.getChain() 匹配请求路径与过滤规则
    • 使用 AntPathMatcher 进行路径匹配
    • 执行匹配到的过滤器链

关键过滤器类对应关系:

过滤器名称 对应类
anon org.apache.shiro.web.filter.authc.AnonymousFilter
authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter
perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter

0x02 CVE-2010-3863

漏洞详情

Shiro 在路径控制时未对传入的 URL 编码进行解码,导致攻击者可以绕过过滤器访问被过滤的路径。

影响版本:Shiro <= 1.0.0

环境搭建

pom.xml 配置:

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.0.0-incubating</version>
</dependency>
<!-- 其他shiro组件版本相同 -->

添加测试路由:

filterMap.put("/secret.html", "authc,roles[admin]");

漏洞复现与分析

PoC: /./secret.html

漏洞原理:

  1. 请求 /./secret.html 进入 PathMatchingFilterChainResolver.getChain()
  2. Shiro 将路径拆分为 ["." , "secret.html"]
  3. 与配置的 /secret.html 不匹配
  4. 最终匹配 /** 的匿名访问规则,绕过认证

关键代码路径:

org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain()
-> pathMatches()
-> org.apache.shiro.util.AntPathMatcher#doMatch()

修复方案

Shiro 添加了路径标准化函数,处理 ////.//../ 等特殊路径。

0x03 CVE-2016-6802

漏洞详情

Shiro 未对 ContextPath 做路径标准化导致权限绕过。

影响版本:Shiro < 1.3.2

漏洞复现

PoC: /aa/../drunkbaby/listProduct.jsp

漏洞分析

  1. 请求进入 WebUtils#getPathWithinApplication()
  2. getContextPath() 处理不一致:
    • Shiro 获取的 contextPath 为 /aa/../drunkbaby
    • 与实际 contextPath /drunkbaby 不匹配
  3. 导致后续路径匹配失败,绕过权限检查

关键代码路径:

org.apache.shiro.web.util.WebUtils#getPathWithinApplication()
-> getContextPath()
-> org.apache.catalina.connector.Request#getContextPath()

修复方案

Shiro 在 1.3.2 版本中对 ContextPath 进行标准化处理:

normalize(decodeRequestString(request, uri))

0x04 CVE-2020-1957 (Shiro682)

漏洞详情

Spring 与 Shiro 对路径结尾 / 处理差异导致权限绕过。

影响版本:Shiro <= 1.5.1

漏洞复现

PoC: /user/add/

漏洞分析

  1. Shiro 将 /user/add/user/add/ 视为不同路径
  2. Spring 将两者视为相同路径
  3. 配置 /user/add 需要认证,但访问 /user/add/ 可绕过

关键代码对比:

  • Shiro 路径匹配:org.apache.shiro.util.AntPathMatcher#doMatch()
  • Spring 路径匹配:org.springframework.web.servlet.mvc.condition.PatternsRequestCondition#getMatchingPatterns()

修复方案

Shiro 1.5.2 版本中:

  • 对路径结尾的 / 进行统一处理
  • 迁就 Spring 的路径处理方式

0x05 CVE-2020-11989

漏洞详情

双层编码绕过,需要特定条件:

  1. ant 风格配置为 * 而非 **
  2. Controller 使用 @PathVariable 且参数类型为 String

影响版本:Shiro < 1.5.3

漏洞复现

PoC: /toJsonList/r%25%32%66oot

漏洞分析

  1. Shiro 获取的路径:/toJsonList/r/oot(不匹配 /toJsonList/*
  2. Spring 解码后:/toJsonList/r%2foot
  3. 导致权限检查绕过

关键点:

org.apache.shiro.web.util.WebUtils#getRequestUri()
-> decodeAndCleanUriString()

修复方案

Shiro 1.5.3 修改路径获取方式:

  • 使用 getPathWithinApplication() 方法
  • 改为 getServletPath(request) + getPathInfo(request) 拼接

0x06 CVE-2020-13933

漏洞详情

分号(;)编码绕过,与 CVE-2020-11989 类似但使用 %3b

影响版本:Shiro < 1.6.0

漏洞复现

PoC: /toJsonList/%3broot

漏洞分析

  1. Shiro 的 removeSemicolon() 移除分号,得到 /toJsonList/
  2. 与配置的 /toJsonList/* 不匹配
  3. Spring 处理时先移除分号再解码,路径有效

修复方案

Shiro 1.6.0 新增全局 InvalidRequestFilter,过滤特殊字符(分号、反斜线、非ASCII字符)。

0x07 CVE-2020-17510

漏洞详情

使用 . 编码(%2e)绕过路径匹配。

影响版本:Shiro < 1.7.0

漏洞复现

PoC: /toJsonList/%2e

漏洞分析

  1. Shiro 解码后路径:/toJsonList/.
  2. 标准化后:/toJsonList/
  3. /toJsonList/* 不匹配,绕过检查

修复方案

Shiro 1.7.0 新增 ShiroUrlPathHelper 类,重写路径处理方法。

0x08 CVE-2020-17523

漏洞详情

CVE-2020-17510 修复后的绕过,使用空格(%20)。

影响版本:Shiro < 1.7.1

漏洞复现

PoC: /toJsonList/%20

修复方案

Shiro 1.7.1 修改 AntPathMatchertokenizeToStringArray 方法参数。

0x09 CVE-2021-41303

漏洞详情

特定配置下路径匹配逻辑问题导致绕过。

影响版本:Shiro = 1.7.1

漏洞复现

配置:

filterMap.put("/toJsonList/*", "authc");
filterMap.put("/toJsonList/index", "authc");

Controller:

@GetMapping("/toJsonList/{name}/index")
public String namePage(@PathVariable String name) {
    return name;
}

PoC: /toJsonList/xxx/index

漏洞分析

  1. Shiro 1.7.1 路径匹配逻辑变更:
    • 先比较 pathPattern 和 requestURI
    • 不匹配则比较去除尾部斜线的版本
  2. 导致特定配置下绕过

修复方案

Shiro 1.8.0 修改 filterChainManager.proxy 参数传递方式。

0x10 总结

Shiro 权限绕过漏洞主要成因:

  1. 路径处理不一致(Shiro 与 Spring/Tomcat)
  2. 编码解码顺序问题
  3. 特殊字符处理差异
  4. 路径标准化不完善

防护建议:

  1. 及时升级 Shiro 到最新版本
  2. 统一路径处理逻辑
  3. 严格校验特殊字符
  4. 采用最小权限原则配置

通过分析这些漏洞,可以深入理解 Shiro 的安全机制和常见问题,为安全开发和审计提供参考。

Apache Shiro 权限绕过多漏洞分析与教学文档 0x00 前言 Apache Shiro 是一个强大且易用的 Java 安全框架,提供认证、授权、加密和会话管理等功能。本文详细分析 Shiro 框架中的多个权限绕过漏洞(CVE-2010-3863、CVE-2016-6802、CVE-2020-1957、CVE-2020-11989、CVE-2020-13933、CVE-2020-17510、CVE-2020-17523、CVE-2021-41303),从环境搭建到漏洞原理分析,再到修复方案,全面剖析 Shiro 权限绕过漏洞。 0x01 Shiro 基础与流程分析 环境搭建 实现 Shiro 使用需要三个核心模块: 创建 Realm 对象(自定义类) DefaultWebSecurityManager ShiroFilterFactoryBean 核心配置示例: Shiro 认证流程 初始化阶段 : ShiroFilterFactoryBean 实现 FactoryBean 接口,Spring 初始化时调用 getObject() 方法 创建 FilterChainManager 管理过滤链 添加默认过滤器(anon、authc、perms等) 应用全局属性(loginUrl、successUrl、unauthorizedUrl) 加载自定义过滤器规则 请求处理阶段 : Tomcat 收到请求后,调用 Shiro 的 OncePerRequestFilter 通过 PathMatchingFilterChainResolver.getChain() 匹配请求路径与过滤规则 使用 AntPathMatcher 进行路径匹配 执行匹配到的过滤器链 关键过滤器类对应关系: | 过滤器名称 | 对应类 | |------------|--------| | anon | org.apache.shiro.web.filter.authc.AnonymousFilter | | authc | org.apache.shiro.web.filter.authc.FormAuthenticationFilter | | perms | org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter | | roles | org.apache.shiro.web.filter.authz.RolesAuthorizationFilter | 0x02 CVE-2010-3863 漏洞详情 Shiro 在路径控制时未对传入的 URL 编码进行解码,导致攻击者可以绕过过滤器访问被过滤的路径。 影响版本 :Shiro <= 1.0.0 环境搭建 pom.xml 配置: 添加测试路由: 漏洞复现与分析 PoC : /./secret.html 漏洞原理: 请求 /./secret.html 进入 PathMatchingFilterChainResolver.getChain() Shiro 将路径拆分为 ["." , "secret.html"] 与配置的 /secret.html 不匹配 最终匹配 /** 的匿名访问规则,绕过认证 关键代码路径: 修复方案 Shiro 添加了路径标准化函数,处理 / 、 // 、 /./ 、 /../ 等特殊路径。 0x03 CVE-2016-6802 漏洞详情 Shiro 未对 ContextPath 做路径标准化导致权限绕过。 影响版本 :Shiro < 1.3.2 漏洞复现 PoC : /aa/../drunkbaby/listProduct.jsp 漏洞分析 请求进入 WebUtils#getPathWithinApplication() getContextPath() 处理不一致: Shiro 获取的 contextPath 为 /aa/../drunkbaby 与实际 contextPath /drunkbaby 不匹配 导致后续路径匹配失败,绕过权限检查 关键代码路径: 修复方案 Shiro 在 1.3.2 版本中对 ContextPath 进行标准化处理: 0x04 CVE-2020-1957 (Shiro682) 漏洞详情 Spring 与 Shiro 对路径结尾 / 处理差异导致权限绕过。 影响版本 :Shiro <= 1.5.1 漏洞复现 PoC : /user/add/ 漏洞分析 Shiro 将 /user/add 和 /user/add/ 视为不同路径 Spring 将两者视为相同路径 配置 /user/add 需要认证,但访问 /user/add/ 可绕过 关键代码对比: Shiro 路径匹配: org.apache.shiro.util.AntPathMatcher#doMatch() Spring 路径匹配: org.springframework.web.servlet.mvc.condition.PatternsRequestCondition#getMatchingPatterns() 修复方案 Shiro 1.5.2 版本中: 对路径结尾的 / 进行统一处理 迁就 Spring 的路径处理方式 0x05 CVE-2020-11989 漏洞详情 双层编码绕过,需要特定条件: ant 风格配置为 * 而非 ** Controller 使用 @PathVariable 且参数类型为 String 影响版本 :Shiro < 1.5.3 漏洞复现 PoC : /toJsonList/r%25%32%66oot 漏洞分析 Shiro 获取的路径: /toJsonList/r/oot (不匹配 /toJsonList/* ) Spring 解码后: /toJsonList/r%2foot 导致权限检查绕过 关键点: 修复方案 Shiro 1.5.3 修改路径获取方式: 使用 getPathWithinApplication() 方法 改为 getServletPath(request) + getPathInfo(request) 拼接 0x06 CVE-2020-13933 漏洞详情 分号( ; )编码绕过,与 CVE-2020-11989 类似但使用 %3b 。 影响版本 :Shiro < 1.6.0 漏洞复现 PoC : /toJsonList/%3broot 漏洞分析 Shiro 的 removeSemicolon() 移除分号,得到 /toJsonList/ 与配置的 /toJsonList/* 不匹配 Spring 处理时先移除分号再解码,路径有效 修复方案 Shiro 1.6.0 新增全局 InvalidRequestFilter ,过滤特殊字符(分号、反斜线、非ASCII字符)。 0x07 CVE-2020-17510 漏洞详情 使用 . 编码( %2e )绕过路径匹配。 影响版本 :Shiro < 1.7.0 漏洞复现 PoC : /toJsonList/%2e 漏洞分析 Shiro 解码后路径: /toJsonList/. 标准化后: /toJsonList/ 与 /toJsonList/* 不匹配,绕过检查 修复方案 Shiro 1.7.0 新增 ShiroUrlPathHelper 类,重写路径处理方法。 0x08 CVE-2020-17523 漏洞详情 CVE-2020-17510 修复后的绕过,使用空格( %20 )。 影响版本 :Shiro < 1.7.1 漏洞复现 PoC : /toJsonList/%20 修复方案 Shiro 1.7.1 修改 AntPathMatcher 的 tokenizeToStringArray 方法参数。 0x09 CVE-2021-41303 漏洞详情 特定配置下路径匹配逻辑问题导致绕过。 影响版本 :Shiro = 1.7.1 漏洞复现 配置: Controller: PoC : /toJsonList/xxx/index 漏洞分析 Shiro 1.7.1 路径匹配逻辑变更: 先比较 pathPattern 和 requestURI 不匹配则比较去除尾部斜线的版本 导致特定配置下绕过 修复方案 Shiro 1.8.0 修改 filterChainManager.proxy 参数传递方式。 0x10 总结 Shiro 权限绕过漏洞主要成因: 路径处理不一致(Shiro 与 Spring/Tomcat) 编码解码顺序问题 特殊字符处理差异 路径标准化不完善 防护建议: 及时升级 Shiro 到最新版本 统一路径处理逻辑 严格校验特殊字符 采用最小权限原则配置 通过分析这些漏洞,可以深入理解 Shiro 的安全机制和常见问题,为安全开发和审计提供参考。