Apache Shiro 身份验证绕过漏洞 复现(CVE-2020-11989)

た 入场券 2024-04-07 10:47 146阅读 0赞

0x00 漏洞简述

Apache Shiro 1.5.3之前的版本中,当将Apache Shiro与Spring动态控制器一起使用时,精心编制的请求可能会导致绕过身份验证,如果直接访问 /shiro/admin/page ,会返回302跳转要求登录,访问 /;/shiro/admin/page , 就能直接绕过Shiro权限验证,访问到/admin路由中的信息

0x01 漏洞影响

Apache Shiro 1.5.3之前的版本

Spring 框架中只使用 Shiro 鉴权

0x02 环境搭建

1.下载项目到本地https://github.com/l3yx/springboot-shiro

2.通过idea编辑器对其进行编译成war包,然后讲放入到tomcat下的webapps目录中,运行即可。

这里已编译好war包:

https://github.com/backlion/demo/blob/master/shiro.war

0x03 漏洞复现

1.权限配置如下,其中/admin下的路由需要登录才能访问

  1. @Bean
  2. ShiroFilterFactoryBean shiroFilterFactoryBean(){
  3. ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
  4. bean.setSecurityManager(securityManager());
  5. bean.setLoginUrl("/login");
  6. bean.setSuccessUrl("/index");
  7. bean.setUnauthorizedUrl("/unauthorizedurl");
  8. Map<String, String> map = new LinkedHashMap<>();
  9. map.put("/doLogin", "anon");
  10. map.put("/admin/*", "authc");
  11. bean.setFilterChainDefinitionMap(map);
  12. return bean;
  13. }
  14. ---
  15. @GetMapping("/admin/page")
  16. public String admin() {
  17. return "admin page";
  18. }

2.maven打包项目为shiro.war,部署于Tomcat。该漏洞成功利用存在下面两个条件

  1. 应用不能部署根目录root目录下,也就是需要context-path,server.servlet.context-path=/shiro,如果为根目录则context-path为空,就会被CVE-2020-1957的patch将URL格式化,值得注意的是若Shiro版本小于1.5.2的话那么该条件就不需要。
  2. Spring控制器中没有另外的权限校验代码

3.如果直接访问 /shiro/admin/page ,会返回302跳转要求登录

48da148bde6a791a97eaaf1c41f868e9.png

4.但是访问 /;/shiro/admin/page , 就能直接绕过Shiro权限验证,访问到/admin路由中的信息

e5721b2e78c10b6d86e99c8820b6a4bf.png

0x04 漏洞分析

由于Shiro的权限校验是通过判断url匹配来做的,如果能找到Shiro获取的url与Web框架处理url不一致的情况就能造成权限绕过。Shiro中对于URL的获取及匹配在org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain

以访问/;/shiro/admin/page举例,通过getPathWithinApplication函数得到的路径为/

85c59ddbdc6743d4db718b7ede557acb.jpeg

跟入该函数的处理逻辑

org.apache.shiro.web.util.WebUtils#getPathWithinApplication

34a85167c01f032db44a2d2e07a702ab.jpeg

可以看到 org.apache.shiro.web.util.WebUtils#getRequestUri 获取到的是/

e2900c3bd2e38bc81002d66da8826e43.jpeg

这里分别通过getContextPath() getServletPath() getPathInfo()获取并拼接得到/;/test//admin/page,传入后decodeAndCleanUriString变成了/,

org.apache.shiro.web.util.WebUtils#decodeAndCleanUriString

c11bec1b1327e974f4ee1dcbf565bc73.jpeg

在decodeAndCleanUriString,会根据ascii为59的字符也就是;进行URL的截断,所以最终返回了/

回到最开始的/;/shiro/admin/page请求,该request请求会进入spring中,spring处理url函数如下

org.springframework.web.util.UrlPathHelper#getPathWithinServletMapping

0f7c397e04377224634445fbf39fc6c7.jpeg

53b921e5a47e4d6184fcb39a9d638437.png

在getPathWithinApplication处理下是能正确获取到context-path与路由,最终经过getPathWithinServletMapping函数格式化处理后,得到最终路径为/admin/page,所以我们可以正常访问到该页面

22ff05f80c10c3104c8a79b7a6e46e51.png

因此总结来说就是当URL进入到Tomcat时,Tomcat判断/;shiro/admin/page ,为shiro应用下的/admin/page路由,进入到Shiro时被;截断被认作为/,再进入Spring时又被正确处理为test应用下的/admin/page路由,最后导致shiro的权限绕过。

0x05 漏洞修复

升级到最新版,官方已在新版本中修复了该漏洞

0x06 参考文献

https://l3yx.github.io/2020/06/30/Shiro-%E6%9D%83%E9%99%90%E7%BB%95%E8%BF%87%E6%BC%8F%E6%B4%9E-CVE-2020-11989/

https://xz.aliyun.com/t/8223

发表评论

表情:
评论列表 (有 0 条评论,146人围观)

还没有评论,来说两句吧...

相关阅读