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




