Shiro权限绕过漏洞分析学习
Shiro 权限绕过漏洞分析学习
环境:
downgit下载源码然后放入idea,简单修改一下测试用例
shiro跟这个函数跟一下基本就能过一遍
PathMatchingFilterChainResolver#getChain
其中getPathWithinApplication重点处理uri
spring从DispatcherServlet#doDispatch跟,以下是函数堆栈
重点看下其中的getPathWithinApplication大致就能了解
getMatchingPatterns:260, PatternsRequestCondition (org.springframework.web.servlet.mvc.condition)
getMatchingCondition:247, PatternsRequestCondition (org.springframework.web.servlet.mvc.condition)
getMatchingCondition:262, RequestMappingInfo (org.springframework.web.servlet.mvc.method)
getMatchingMapping:95, RequestMappingInfoHandlerMapping (org.springframework.web.servlet.mvc.method)
getMatchingMapping:59, RequestMappingInfoHandlerMapping (org.springframework.web.servlet.mvc.method)
addMatchingMappings:428, AbstractHandlerMethodMapping (org.springframework.web.servlet.handler)
lookupHandlerMethod:389, AbstractHandlerMethodMapping (org.springframework.web.servlet.handler)
getHandlerInternal:367, AbstractHandlerMethodMapping (org.springframework.web.servlet.handler)
getHandlerInternal:110, RequestMappingInfoHandlerMapping (org.springframework.web.servlet.mvc.method)
getHandlerInternal:59, RequestMappingInfoHandlerMapping (org.springframework.web.servlet.mvc.method)
getHandler:396, AbstractHandlerMapping (org.springframework.web.servlet.handler)
getHandler:1234, DispatcherServlet (org.springframework.web.servlet)
doDispatch:1016, DispatcherServlet (org.springframework.web.servlet)
Shiro < 1.3.2 验证绕过漏洞 CVE-2016-6802
配置:必须得配,任意即可,因为是这里的上下文路径出现了漏洞,request.getContextPath()获取的是项目名 如现在的/web
小于1.3.2即可
通过任意路径+../ + /web就能绕过
原理分析
getContextPath函数没有做标准化处理
而requestUri会进行标准化将/../与前面一个'/'后的内容消除
然后进行StringUtils.startsWiithIgnoreCase比较 正常情况下应该返回/hello/1 现在把requesturl整个返回,/web/hello/1
后面的模式肯定匹配不上了,因为正常不包含/web
补丁:https://github.com/apache/shiro/commit/b15ab927709ca18ea4a02538be01919a19ab65af
getContextPath加入标准化
Shiro < 1.5.2 验证绕过漏洞 CVE-2020-1957
shiro1.5.2以下即可
两种方法绕过
通过;绕过:
首先在获得uri这一步getRequestUri中decodeAndCleanUriString,
直接把分号以及后面所有清除了,url由此变成 /hello 不匹配/hello/*,无需通过验证
接着看spring对uri的处理,思路很简单,看哪一个函数对;进行了处理,removeSemicolonContentInternal,spring只是单纯把;以及;后面'/'前的字符去掉了
也就是做安全校验的时候是/hello 通过shiro 访问时是spring的/hello/1路由,用到了两者对特殊符号处理的不一致
第二种通过/hello/1/绕过
同样看shiro的处理方式,看这个函数requestUri没有对尾部的/处理
而匹配时的这段逻辑对尾部的/处理印证了shiro认为/1 和/1/是两个路径
再看spring,也是没有对尾部的/做处理
但在比较的时候,加了一步处理,也就是spring认为/hello==/hello/,所以成功访问
补丁:
对于通过加上/绕过的方式,shiro加上了额外的判断,去掉尾部/后再匹配
而对于分号,使用getServletPath()做到了和spring对分号同样处理的效果
Apache Shiro < 1.5.3 权限绕过漏洞 CVE-2020-11989
两次url编码绕过,原理很简单,因为shiro会进行两次解码,而spring只会解码一次
/ -> %2f ->%25%32%66
1.5.2
接受的类型参数必须得是string类型
shiro进行了两次解码,这里的/hello/a/a匹配不上/hello/*
spring此处解码一次,然后当成hello/a%2fa访问路由了
补丁:
将RequestUri-ContextPath 变为getServletPath+getPathInfo同时解决二次解码问题
Shiro < 1.6.0 验证绕过漏洞 CVE-2020-13933
环境shiro1.5.3
其他和上面一致
其实和上面这个思路有点像,上面是通过了对/的差异,给shiro增加了一个路径,而下面是通过shiro对;减少了一个路径而spring由于先去分号后解码而没有减去此路径造成差异
还是同样经过getServletPath处理为了/hello/,消除了;后面的部分,造成了校验绕过
spring还是没变是先进行了去除; 然后解码也就是访问了/web/hello/;a
补丁:增加全局的过滤器,直接过滤;以及其编码
Apache Shiro < 1.7.0 权限绕过漏洞 CVE-2020-17510
shiro1.6.0
且springboot必须大于2.3.0.RELEASE
还是getServletPath的标准化处理把.处理掉了,导致匹配不上
再看spring,首先是alwaysUseFullPath 在2.3.0.RELEASE之前默认为false,之后为true,所以之后是直接返回了/web/hello/.
而如果在这个版本之前进入getPathWithinServletMapping,进行getServletPath(),去掉了.
补丁:重写了两个函数但仍然可以攻击
这里在1.7.1的补丁中修复的
1.7.1中是对后面的.消除但更改了不减去/的一步,解决了/hello/ 不能匹配 /hello/{1}的核心问题
Apache Shiro < 1.7.1 权限绕过漏洞CVE-2020-17523
shiro 1.7.0版本
/web/hello/%20进行了绕过
其实是对空格解码之后并未消除 最后穿过去的比较的是"/hello/ ",尾部是空格
最重要的是这一步的比较,在pathDirs数组时,空格直接被忽略了
跟进一看便知,被trim()了 ,导致和/hello的效果完全一致,后面spring
spring也确实访问了"/web/hello/ "
补丁:
更改了函数,第三个参数false默认不执行trim()
Apache shiro < 1.8.0 认证机制不恰当 CVE-2021-41303
shiro1.7.1
配置这样
正常访问/hello/1,而/hello/1/能绕过
分析:
do,while循环这个本质的意思其实就是每次都要把尾部没有去/和尾部去了的与,当前uri比较,而不同的是图中所示的地方,requestURINoTrailingSlash是可控的,不是真正比较时的匹配项. 这里意思其实就是比如我用/hello/* 与/hello/1 作比较,结果你去找的相对应的权限是/hello/1 而不是真正匹配项/hello/*,这就导致了存在绕过
而绕过也很简单/hello/1/ 即可绕过第一处的/hello/* 因为比较的没去/的uri ,而第二处去掉了之后/hello/* 与 /hello/1成功匹配
但是找权限找的/hello/1的 ,所以导致可绕过
补丁:
自然就是换成pathPattern即可
Apache Shiro < 1.9.1 RegExPatternMatcher 权限绕过漏洞 CVE-2022-32532
shiro<1.9.1
然后目标配置了RegExPatternMatcher情况下且正则规则中包含了“.”则存在漏洞
Java的正则.默认不匹配\n \r 字符
DOTALL模式可以匹配\n
在RegExPatternMatcher中使用的模式不是DOTALL,即导致绕过
参考https://github.com/Lay0us/CVE-2022-32532配置filter
成功绕过
补丁:
过滤一下特殊字符