shiro历史漏洞分析—CVE-2020-1957漏洞

admin 2022年9月23日09:43:39安全文章评论5 views3597字阅读11分59秒阅读模式

出品|先知社区(ID:alter99)

声明

以下内容,来自先知社区的alter99作者原创,由于传播,利用此文所提供的信息而造成的任何直接或间接的后果和损失,均由使用者本人负责,长白山攻防实验室以及文章作者不承担任何责任。


CVE-2020-1957

漏洞信息

漏洞编号:

CVE-2020-1957/CNVD-2020-20984/SHIRO-682
影响版本:shiro < 1.5.2
漏洞描述:利用Shiro和Spring对URL的处理的差异化,越权并成功访问。
漏洞补丁:Commit Commit Commit
参考:Shiro权限绕过漏洞详细分析Ruil1n师傅


漏洞分析

SHIRO-682

本漏洞起源于 SHIRO-682。在Spring中,/resource/xx与/resource/xx/都会被截成/resource/xx以访问相应资源;在shiro中,/resource/xx与/resource/xx/被视为两个不同路径。所以在Spring集成shiro时,只需要在访问路径后添加/就存在绕过权限校验的可能。


下面通过复现进行分析(分析、测试版本1.4.2):
首先shiro.ini中[urls]配置如下:

[urls]# anon:匿名拦截器,不需登录就能访问,一般用于静态资源,或者移动端接口。# authc:登录拦截器,需要登录认证才能访问的资源。/login.jsp = authc/logout = logout/toJsonPOJO = authc, perms["audit:list"]/** = anon

输入/toJsonPOJO时,shiro对其进行判断,从shior.ini或其他配置中进行匹配。当匹配到/toJsonPOJO时,匹配成功,跳出循环。

shiro历史漏洞分析—CVE-2020-1957漏洞

此时,跳转至登陆界面。
输入/toJsonPOJO/时,shiro对其进行判断,当匹配到/toJsonPOJO时,匹配失败,继续匹配;当匹配到/**时,匹配成功,跳出循环。

shiro历史漏洞分析—CVE-2020-1957漏洞

接着到了springframework中的判断,这里/toJson-POJO/和/toJsonPOJO是可以匹配成功的

shiro历史漏洞分析—CVE-2020-1957漏洞

此时,成功绕过

shiro历史漏洞分析—CVE-2020-1957漏洞


其他绕过方式

除了上面的绕过方式,本CVE还存在另一个绕过。利用的是shiro和spring对url中的 ; 处理的差异进行绕过并成功访问。分析、测试版本1.4.2


绕过分析

首先进入Shiro中,首先在

org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver.class#getChain处下断点,进行调试,访问http://localhost:8080/xx/..;/toJsonPOJO

shiro历史漏洞分析—CVE-2020-1957漏洞

单步调试进入this.getPathWithinApplicat-ion(request),在WebUtils#getPathWithinApplicat-ion()中,通过getContextPath(request),获取到上下文信息后,再用getRequestUri(request)获取具体的uri。进入getRequestUri()方法,在return前,获取到的uri为/xx/..;/toJsonPOJO

shiro历史漏洞分析—CVE-2020-1957漏洞

接下来分析一下return normalize(decodeAndClean-UriString(request, uri));

首先进入decodeAndCleanUriString


传入的参数uri是/xx/..;/toJsonPOJO,然后通过语句int semicolonIndex= uri.indexOf(59);找出uri中分号的位置,59也就是;的ASCII码


如果uri中有分号,就返回分号前的字段,否则返回整个uri。

shiro历史漏洞分析—CVE-2020-1957漏洞

接着进入normalize,参数uri已经变成/xx/..,normalize内部对传入的路径进行标准化规范处理,相关操作包括替换反斜线、替换//为/等,最后得到返回的uri


此时return normalize(decodeAndCleanUriString-(request, uri));结果为/xx/..,也就是说getRequestUri(request)获取的uri为/xx/..

shiro历史漏洞分析—CVE-2020-1957漏洞

shiro历史漏洞分析—CVE-2020-1957漏洞

一路回到getChain,经过上面的步骤,得到requestURI值为/xx/..,接下来在while循环里使用pathMatches(pathPattern, requestURI)进行权限校验,此时只有/**能够与/xx/..匹配成功,/**是anon权限,不需要登陆就能访问,绕过了/toJsonPOJO的authc权限

shiro历史漏洞分析—CVE-2020-1957漏洞


此时Shiro部分的权限绕过了,那么Spring部分的路径是怎么匹配的呢?


url经过shiro的处理认证通过后,就会进入spring中进行解析,我们在UrlPathHelper#getLookupPath-ForRequest下断点

shiro历史漏洞分析—CVE-2020-1957漏洞

先进入getPathWithinApplication(),通过this.get-RequestUri(request)获取uri

shiro历史漏洞分析—CVE-2020-1957漏洞

获取到的uri值为/xx/..;/toJsonPOJO,在return之前进入decodeAndCleanUriString(request, uri)

shiro历史漏洞分析—CVE-2020-1957漏洞

传进来的参数uri为/xx/..;/toJsonPOJO,经过removeSemicolonContent(uri)后移除uri中/与/之间的的分号以及分号后面的内容;

经过decodeRequestString(request, uri)后对uri进行解码;经过getSanitized-Path(uri)后将路径中//替换为/。此时返回的uri值为/xx/../toJsonPOJO

shiro历史漏洞分析—CVE-2020-1957漏洞

shiro历史漏洞分析—CVE-2020-1957漏洞

步入getPathWithinServletMapping()后,传入的参数pathWithinApp值为/xx/../toJsonPOJO。


依次通过UrlPathHelper#getServletPath

HttpServletRequestWrapper#getServletPath

Request#getServletPath获取到我们实际访问的url:http://localhost:8080/toJsonPOJO后返回,最终实现绕过权限访问

shiro历史漏洞分析—CVE-2020-1957漏洞

shiro历史漏洞分析—CVE-2020-1957漏洞

经过测试当uri为

123;/..;345/;../.;/alter/..;/;/;///////;/;/;awdwadwa/toJsonPOJO时,Shiro对/123进行权限验证;

shiro历史漏洞分析—CVE-2020-1957漏洞

Spring的org.springframework.web.util.UrlPathHelper中,getPathWithinApplication(request)值为

/123/.././alter/../toJsonPOJO;

shiro历史漏洞分析—CVE-2020-1957漏洞

shiro历史漏洞分析—CVE-2020-1957漏洞

this.getPathWithinServletMapping(request, pathWithinApp)值为/toJsonPOJO,可以进行绕过

shiro历史漏洞分析—CVE-2020-1957漏洞

上面这个payload只能在较低版本的Spring Boot上使用。


根据Ruil1n 师傅介绍:
当Spring Boot版本在小于等于2.3.0.RELEASE的情况下,alwaysUseFullPath为默认值false,这会使得其获取ServletPath,所以在路由匹配时相当于会进行路径标准化包括对%2e解码以及处理跨目录,这可能导致身份验证绕过。


而反过来由于高版本将alwaysUseFullPath自动配置成了true从而开启全路径,又可能导致一些安全问题。


所以在高版本上只能试着寻找逻辑上有没有漏洞,然后进行绕过。比如程序配置了访问路径/alter/** 为 anon,但是指定了其中的一个/alter/page为 authc。这时在不跳目录的情况下,可以使用如下请求绕过:
http://127.0.0.1:8080/alter//;aaaa/;...///////;/;/;awdwadwa/page


漏洞修复

先是在Commit的PathMatchingFilter#pathsMatch和PathMatchingFilterCha-inResolver#getChain方法中添加了对访问路径后缀为/的支持

shiro历史漏洞分析—CVE-2020-1957漏洞

然后在Commit,除了endsWith还添加了equals的判断。是修复由于上一次提交,导致访问路径为/时抛出的异常。


在Commit中,shiro使用request.getContextPath()、request.getServletPath-()、request.getPathInfo()拼接构造uri替代request.getRequestURI()来修复; 绕过

shiro历史漏洞分析—CVE-2020-1957漏洞


shiro历史漏洞分析—CVE-2020-1957漏洞
shiro历史漏洞分析—CVE-2020-1957漏洞
shiro历史漏洞分析—CVE-2020-1957漏洞

▇ 扫码关注我们 ▇

长白山攻防实验室

学习最新技术知识


原文始发于微信公众号(长白山攻防实验室):shiro历史漏洞分析—CVE-2020-1957漏洞

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年9月23日09:43:39
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  shiro历史漏洞分析—CVE-2020-1957漏洞 http://cn-sec.com/archives/1312489.html

发表评论

匿名网友 填写信息

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