CVE-2020-17523_Apache_Shiro身份认证绕过
CVE-2020-17523
漏洞描述
Apache Shiro身份认证绕过漏洞
漏洞成因
Shiro中对于URL的获取及匹配在org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain
先看下这个getChain
方法:
1 | public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) { |
其中DEFAULT_PATH_SEPARATOR
值被定义为/
该方法先检查requestURI
是否以/
结尾,如果是,就删掉最后一个/
。
然后在匹配路径的循环中,会先判断下路径规则pathPattern是否以/
结尾,如果是也会删除。然后再去调用pathMatches()
方法进行路径匹配。因此两种利用方式中,是否以/
结尾都没有关系,因为开始经过getChain
方法就会被删除。
空格绕过法分析
关注下pathMatches()
方法:
1 | protected boolean pathMatches(String pattern, String path) { |
追踪发现最终 matches(pattern, path)
调用了AntPathMatcher.java#doMatch
测试一下pathMatches("/admin/*","/admin/1")
和pathMatches("/admin/*","/admin/ ")
,前者正常匹配,后者匹配失败。
开始调试,一直到doMatch("/admin/*","/admin/ ")
。可见,tokenizeToStringArray
返回的pathDirs已经没有第二层路径了。因此会导致/admin/*
和/admin
不匹配。
跟一下tokenizeToStringArray
方法,发现其调用tokenizeToStringArray
方法时的trimTokens
参数为true。
而tokenizeToStringArray
方法,在参数trimTokens
为true时,会经过trim()
处理,因此导致空格被清除。再次返回getChain
时最后一个/
被删除。因此tokenizeToStringArray
返回的pathDirs没有第二层路径。
总结一下:存在漏洞的shiro版本,由于调用tokenizeToStringArray
方法时,trimTokens
参数默认为true,空格会经过trim()
处理,因此导致空格被清除。再次返回getChain
时最后一个/
被删除,所以/admin
与/admin/*
匹配失败,导致鉴权绕过。而Spring接受到的访问路径为/admin/%20
,按照正常逻辑返回响应,因此导致权限被绕过。
/./绕过分析
分析normalize()
方法,此方法在org.apache.*shiro*.web.util.WebUtils#normalize
1 | private static String normalize(String path, boolean replaceBackSlash) { |
其功能是:
条件 | 示例 |
---|---|
正斜杠处理成反斜杠 | \ -> / |
双反斜杠处理成反斜杠 | // -> / |
以/.或者/…结尾,则在结尾添加/ | /. -> /./ /… -> /…/ |
归一化处理/./ | /./ -> / |
路径跳跃 | /aaa/…/bbb -> /bbb |
所以/admin/.
在被处理成/admin/./
之后变成了/admin/
。
再经过org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain
处理,由于/
结尾,如果是,就删掉最后一个/
,变成了/admin
。/admin
与/admin/*
不匹配,因此绕过了shiro鉴权。
漏洞影响面
Apache Shiro < 1.7.1
复现步骤
下载shiro 1.7.0环境, 运行
-
%20
绕过访问
http://10.17.34.7:9090/admin/%20
%2e
绕过
访问http://10.17.34.7:9090/admin/%2e