https://img2024.cnblogs.com/blog/3305226/202503/3305226-20250331155133325-143341361.jpg

Shiro权限绕过漏洞分析学习

Shiro 权限绕过漏洞分析学习

环境:

https://www.itsvse.com/downgit/#/home?url=https:%2F%2Fgithub.com%2Flenve%2Fjavaboy-code-samples%2Ftree%2Fmaster%2Fshiro%2Fshiro-basic

downgit下载源码然后放入idea,简单修改一下测试用例

image-20250411190017766

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

image-20250412135444862

小于1.3.2即可

image-20250412135537612

通过任意路径+../ + /web就能绕过

image-20250412135742054

原理分析

getContextPath函数没有做标准化处理

image-20250412135905381

而requestUri会进行标准化将/../与前面一个'/'后的内容消除

然后进行StringUtils.startsWiithIgnoreCase比较 正常情况下应该返回/hello/1 现在把requesturl整个返回,/web/hello/1

image-20250412142020009

后面的模式肯定匹配不上了,因为正常不包含/web

image-20250412142149895

补丁:https://github.com/apache/shiro/commit/b15ab927709ca18ea4a02538be01919a19ab65af

getContextPath加入标准化

image-20250412142434348

Shiro < 1.5.2 验证绕过漏洞 CVE-2020-1957

shiro1.5.2以下即可

image-20250412142904119

两种方法绕过

image-20250412143030411

image-20250412143013778

image-20250412143022602

通过;绕过:

首先在获得uri这一步getRequestUri中decodeAndCleanUriString,

image-20250412143457601

直接把分号以及后面所有清除了,url由此变成 /hello 不匹配/hello/*,无需通过验证

image-20250412143529820

接着看spring对uri的处理,思路很简单,看哪一个函数对;进行了处理,removeSemicolonContentInternal,spring只是单纯把;以及;后面'/'前的字符去掉了

也就是做安全校验的时候是/hello 通过shiro 访问时是spring的/hello/1路由,用到了两者对特殊符号处理的不一致

image-20250412144618912

image-20250412144654685

第二种通过/hello/1/绕过

同样看shiro的处理方式,看这个函数requestUri没有对尾部的/处理

而匹配时的这段逻辑对尾部的/处理印证了shiro认为/1 和/1/是两个路径

image-20250412145353327

再看spring,也是没有对尾部的/做处理

image-20250412151622113

但在比较的时候,加了一步处理,也就是spring认为/hello==/hello/,所以成功访问

image-20250412151947063

补丁:

对于通过加上/绕过的方式,shiro加上了额外的判断,去掉尾部/后再匹配

image-20250413145948029

而对于分号,使用getServletPath()做到了和spring对分号同样处理的效果

image-20250413184045239

Apache Shiro < 1.5.3 权限绕过漏洞 CVE-2020-11989

两次url编码绕过,原理很简单,因为shiro会进行两次解码,而spring只会解码一次

/ -> %2f ->%25%32%66

1.5.2

image-20250413190703581

接受的类型参数必须得是string类型

image-20250413193819458

shiro进行了两次解码,这里的/hello/a/a匹配不上/hello/*

image-20250413191947364

spring此处解码一次,然后当成hello/a%2fa访问路由了

image-20250413190940901

补丁:

将RequestUri-ContextPath 变为getServletPath+getPathInfo同时解决二次解码问题

image-20250413192258941

image-20250413193019635

Shiro < 1.6.0 验证绕过漏洞 CVE-2020-13933

环境shiro1.5.3

其他和上面一致

其实和上面这个思路有点像,上面是通过了对/的差异,给shiro增加了一个路径,而下面是通过shiro对;减少了一个路径而spring由于先去分号后解码而没有减去此路径造成差异

image-20250413193905967

还是同样经过getServletPath处理为了/hello/,消除了;后面的部分,造成了校验绕过

image-20250413194426937

spring还是没变是先进行了去除; 然后解码也就是访问了/web/hello/;a

image-20250413194607155

补丁:增加全局的过滤器,直接过滤;以及其编码

image-20250413195425122

image-20250413195405442

Apache Shiro < 1.7.0 权限绕过漏洞 CVE-2020-17510

shiro1.6.0

且springboot必须大于2.3.0.RELEASE

image-20250413200214769

还是getServletPath的标准化处理把.处理掉了,导致匹配不上

image-20250413200507030

再看spring,首先是alwaysUseFullPath 在2.3.0.RELEASE之前默认为false,之后为true,所以之后是直接返回了/web/hello/.

image-20250413201521764

而如果在这个版本之前进入getPathWithinServletMapping,进行getServletPath(),去掉了.

image-20250413201443590

补丁:重写了两个函数但仍然可以攻击

image-20250413203011380

image-20250413203147561

这里在1.7.1的补丁中修复的

1.7.1中是对后面的.消除但更改了不减去/的一步,解决了/hello/ 不能匹配 /hello/{1}的核心问题

image-20250413203310849

Apache Shiro < 1.7.1 权限绕过漏洞CVE-2020-17523

shiro 1.7.0版本

/web/hello/%20进行了绕过

其实是对空格解码之后并未消除 最后穿过去的比较的是"/hello/ ",尾部是空格

image-20250413204211016

最重要的是这一步的比较,在pathDirs数组时,空格直接被忽略了

image-20250413204353432

跟进一看便知,被trim()了 ,导致和/hello的效果完全一致,后面spring

image-20250413204448370

spring也确实访问了"/web/hello/ "

image-20250413204652772

补丁:

更改了函数,第三个参数false默认不执行trim()

image-20250413204854626

Apache shiro < 1.8.0 认证机制不恰当 CVE-2021-41303

shiro1.7.1

配置这样

image-20250413220032425

正常访问/hello/1,而/hello/1/能绕过

image-20250413220412976

image-20250413220427321

分析:

do,while循环这个本质的意思其实就是每次都要把尾部没有去/和尾部去了的与,当前uri比较,而不同的是图中所示的地方,requestURINoTrailingSlash是可控的,不是真正比较时的匹配项. 这里意思其实就是比如我用/hello/* 与/hello/1 作比较,结果你去找的相对应的权限是/hello/1 而不是真正匹配项/hello/*,这就导致了存在绕过

image-20250413220504189

而绕过也很简单/hello/1/ 即可绕过第一处的/hello/* 因为比较的没去/的uri ,而第二处去掉了之后/hello/* 与 /hello/1成功匹配

但是找权限找的/hello/1的 ,所以导致可绕过

补丁:

自然就是换成pathPattern即可

image-20250413220946106

Apache Shiro < 1.9.1 RegExPatternMatcher 权限绕过漏洞 CVE-2022-32532

shiro<1.9.1

然后目标配置了RegExPatternMatcher情况下且正则规则中包含了“.”则存在漏洞

Java的正则.默认不匹配\n \r 字符

image-20250413223113046

DOTALL模式可以匹配\n

image-20250413223221041

在RegExPatternMatcher中使用的模式不是DOTALL,即导致绕过

image-20250413223804923

参考https://github.com/Lay0us/CVE-2022-32532配置filter

成功绕过

image-20250413224020687

image-20250413224008020

补丁:

过滤一下特殊字符

image-20250414131241799

posted @ 2025-04-14 13:53  kudo4869  阅读(205)  评论(0)    收藏  举报