Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)

  • A+
所属分类:javasec_cn
摘要

Apahce Shiro 由于处理身份验证请求时出错 存在 权限绕过漏洞,远程攻击者可以发送特制的HTTP请求,绕过身份验证过程并获得对应用程序的未授权访问。


漏洞简述

Apahce Shiro 由于处理身份验证请求时出错 存在 权限绕过漏洞,远程攻击者可以发送特制的HTTP请求,绕过身份验证过程并获得对应用程序的未授权访问。

风险等级

高危

影响版本

  • Apache Shiro < 1.6.0

漏洞详情

shiro的架构图为

Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
其中最主要的是 Subject,SecurityManager,Realms。

Subject:主体,代表了当前“用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等;即一个抽象概念;所有Subject都绑定到SecurityManager,与Subject的所有交互都会委托给SecurityManager;可以把Subject认为是一个门面;SecurityManager才是实际的执行者;  SecurityManager:安全管理器;即所有与安全有关的操作都会与SecurityManager交互;且它管理着所有Subject;可以看出它是Shiro的核心,它负责与后边介绍的其他组件进行交互,如果学习过SpringMVC,你可以把它看成DispatcherServlet前端控制器;  Realm:域,Shiro从从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。 

漏洞原理

利用idea搭建springboot+shiro进行测试,shiro版本为1.5.3。

   <dependency>             <groupId>org.apache.shiro</groupId>             <artifactId>shiro-core</artifactId>             <version>1.5.3</version>         </dependency>          <dependency>             <groupId>org.apache.shiro</groupId>             <artifactId>shiro-web</artifactId>             <version>1.5.3</version>         </dependency>          <dependency>           <groupId>org.apache.shiro</groupId>           <artifactId>shiro-spring</artifactId>           <version>1.5.3</version> </dependency> 

构建测试代码。

@Configuration public class ShiroConfig {     @Bean     public MyRealm myRealm()     {         return new MyRealm(); }      @Bean     public SecurityManager securityManager() {         DefaultWebSecurityManager manager = new DefaultWebSecurityManager();         manager.setRealm(myRealm());         return manager; }      //filter工厂.设置对应的过滤条件和跳转条件     @Bean     public ShiroFilterFactoryBean shiroFilter() {         ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();         // 设置 SecurityManager         bean.setSecurityManager(securityManager());         bean.setLoginUrl("/login");         Map<String, String> filterMap = new LinkedHashMap<>();         // anon:匿名用户可访问         filterMap.put("/login","anon");         // authc:认证用户可访问         filterMap.put("/read/*", "authc");         bean.setFilterChainDefinitionMap(filterMap);         return bean;     } } 

具体权限对应的定义在DefaultFilter类里。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
访问/read/xx,被302重定向到了/login:
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
而/read/%3bxxx,能够绕过认证:
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
ant风格的路径仅出现一个时才能成功,而*无法绕过,具体原因后面会说。

先来看看shiro的拦截器基础类。

PathMatchingFilter: 提供了基于Ant风格的请求路径匹配功能及拦截器参数解析的功能。  OncePerRequestFilter: 过滤器基类,该基类保证每个请求在任何servlet容器上仅执行一次,另外提供enabled属性,表示是否开启该拦截器实例,默认enabled=true表示开启,如果不想让某个拦截器工作,可以设置为false即可。  AbstractShiroFilter: 是Shiro的入口,根据URL配置的filter,选择并执行相应的filter chain。 

shiro层

shiro 过滤器链调用

接着从源码来分析一下这个漏洞,首先是过滤器的调用,经过ApplicationFilterChain,请求被分派到OncePerRequestFilter过滤器进行拦截,首先调用getAlreadyFilteredAttributeName给我们的自定义过滤器打上标记,并通过判断当前请求中是否有该标记来判断该拦截器是否已经调用过,接着判断是否标记该拦截器不进行工作,
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
如果都没有,那么调用doFilterInternal方法,这里调用的是其子类AbstractShiroFilter#doFilterInternal方法,解析request和response。接着根据请求利用SecurityManager创建WebSubject接口类型的实例,这里采用的是建造者模式。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
返回WebDelegatingSubject,然后调用Subject的execute方法,这里是一个回调,
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
接着在回调里调用executeChain,然后调用getExecutionChain,这里getFilterChainResolver返回PathMatchingFilterChainResolver,是在初始化ShiroFilterFactoryBean里设置的,具体流程不进行分析,该类用于解析出此次请求需要执行的Filter链,在PathMatchingFilterChainResolver内部由FilterChainManager维护着拦截器链,比如DefaultFilterChainManager实现维护着url模式与拦截器链的关系。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
看下getChain,首先获取FilterChainManager,也就是DefaultFilterChainManager,DefaultFilterChainManager默认添加DefaultFilter中声明的拦截器。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)

shiro url 处理

接着调用getPathWithinApplication方法。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
跟到WebUtils#getPathWithinApplication方法, 这里Shiro对url的处理也是造成CVE-2020-11989的一个点。左边是修复之前的1.5.2版本,右边是当前版本1.5.3,采用getRequestUri,而getRequestUri里就进行了url的解码。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
修复之后,采用了标准的url解析,不再对%2f解码。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
getServletPath方法将%3b进行了解码,返回结果如下。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
接着调用removeSemicolon,该方法查找;,并将;及其之后的部分删除,最后再调用normalize,用于操作.和/所带来的影响。本次测试返回/read/。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
接着如果请求的不是/,就去除末尾的/,也就是/read。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
接着获取filterChains所对应的filter,将处理后的url进行匹配。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)

shiro url 匹配

在org.apache.shiro.util.AntPathMatcher#doMatch。 这里把我们定义的ant风格的path和请求的path都以/进行拆分存入数组,pattDirs和pathDirs。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
pattern最后一位是,于是返回false。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
如果是
,会返回true,返回true的话,就会根据config里设置url所对应 filter过滤条件,最后返回ProxiedFilterChain:
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
如果是
,返回false,那么会return null。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
resolved也就是null,最后就返回ApplicationFilterChain,在ApplicationFilterChain里没有任何权限校验。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)

spring 层

原则是Shiro会对Servlet容器的FilterChain进行代理,也就是正常情况下应该返回的ProxiedFilterChain,即先走Shiro自己的Filter体系,然后才会委托给Servlet容器的FilterChain进行Servlet容器级别的Filter链执行。但是我们利用*和%3b的配合绕过了,返回的依然是默认的ApplicationFilterChain,后续调用chain.doFilter。

spring url 处理

spring利用DispatcherServlet来分派请求,他的一个主要作用就是通过HandlerMapping,将请求映射到处理器。在处理过程中会调用getHandler方法。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
跟进getHandlerInternal方法。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
这里会调用 UrlPathHelper#getLookupPathForRequest 方法获取请求的相对路径。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
继续调用getPathWithinApplication方法获取地址。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
然后调用getRequestUri,这里调用decodeAndCleanUriString方法很明显的对url进行解码,也就是/read/;xxxx,于是最终spring处理返回的url就是/read/;xxxx。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
调用完getLookupPathForRequest之后,就是获取请求路径的映射了。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)

spring 获取路径映射

跟入lookupHandlerMethod,在里面会根据请求的url在RequestMappingHandlerMapping对象中去匹配自定义Controller里的方法,而这些映射关系都是在初始化RequestMappingHandlerMapping对象的过程中,根据相关注解获取到的。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
最后调用getMatchingPatterns,在spring的AntPathMatcher#doMatch里,将请求和配置里的url进行匹配,如果匹配成功,返回true,匹配之后,从HandlerMapping中取出该路径所映射的方法,然后通过反射去执行方法。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)

版本修复

在shiro 1.6.0版本中,针对/这种ant风格的配置出现的问题,shiro在org.apache.shiro.spring.web.ShiroFilterFactoryBean.java中默认增加了/的路径配置,以防止出现匹配不成功的情况.
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)
而默认的/
*配置对应了一个新增的类org.apache.shiro.web.filter.InvalidRequestFilter进行过滤,匹配到非法字符就会直接报错。
Apache Shiro 权限绕过漏洞分析(CVE-2020-13933)

总结

该漏洞产生的原因主要是shiro层在处理url上和spring上存在差异,主要是在处理;上的问题,通过构造含有;符号的url即可绕过shiro在权限上的处理,而spring不负责权限管控,所以最终会导致权限绕过。

时间线

  • 2020-08-17 Apache Shiro发布通告
  • 2020-08-18 360-CERT 发布预警
  • 2020-09-22 360-CERT 发布分析

参考链接

转载链接

https://cert.360.cn/report/detail?id=0a56bda5f00172dd642f2b436ed49cc7

相关推荐: Spring Framework反射型文件下载漏洞(CVE-2020-5421)

简介 Spring Framework是 Java 平台的一个开源全栈应用程序框架和控制反转容器实现,一般被直接称为 Spring。 漏洞描述 近日,VMware Tanzu发布安全公告,公布了一个存在于Spring Framework中的反射型文件下载(Re…

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: