(CVE-2020-13933)Apache Shiro \< 1.6.0 身份认证绕过漏洞¶
一、漏洞简介¶
2020年8月18日,Apache Shiro官方发布安全通告 Apache Shiro身份验证绕过漏洞(CVE-2020-13933),经过分析,攻击者可以通过构造特殊的HTTP请求实现身份验证绕过。
二、漏洞影响¶
Apache Shiro \< 1.6.0
三、复现过程¶
漏洞分析¶
根据shiro历史上的认证绕过漏洞,本质问题就是springboot对url的处理和shiro的处理不一致导致的认证绕过。其中shiro的url处理的问题都出在org/apache/shiro/web/util/WebUtils.java
类下面,在return
public static String getPathWithinApplication(HttpServletRequest request) {
return normalize(removeSemicolon(getServletPath(request) + getPathInfo(request)));
}
断点,然后我们去springboot的处理url的地方进行断点,org/springframework/web/util/UrlPathHelper.java
。
在return uri;进行
private String decodeAndCleanUriString(HttpServletRequest request, String uri) {
uri = removeSemicolonContent(uri);
uri = decodeRequestString(request, uri);
uri = getSanitizedPath(uri);
return uri;
}
断点。
访问/test/%3bname,先来到shiro的url处理块,
1.jpg
根据图纸可知,获取到的url在处理前已经进行了一次urldecode。然后在进入removeSemicolon
操作,最后结果集在交给normalize
操作。
根据计算器可知removeSemicolon会把url里;后面的内容给删除(包括;)
2.jpg
跟进removeSemicolon看看。
实现代码如下:
private static String removeSemicolon(String uri) {
int semicolonIndex = uri.indexOf(';');
return (semicolonIndex != -1 ? uri.substring(0, semicolonIndex) : uri);
}
确实是把;后面的内容给删除(包括;)了。
一路F8,最后果然把/test/赋值给requestURI变量了。
3.jpg
根据测试当初访问/test/
4.jpg
可以看到,如果test目录的话,是默认有权限访问的,但是/test/后面的路由是需要验证的。
5.jpg
接着我们来到springboot,看看springboot是怎么处理URL的问题。
6.jpg
uri取到的是/test/;name
,可以看到springboot对url做了三个操作后才返回的,removeSemicolonContent
,decodeRequestString
,getSanitizedPath
。
-
removeSemicolonContent 是把(url未解码前的uri里的;后面的内容给删除)
-
decodeRequestString把uri进行urldecode编码
-
getSanitizedPath 是把"//" 替换成 "/"
这是简单对比下shiro的对url的操作顺序:
-
uri 进行urldecode
-
uri 删除;后面的内容,包括;
因为shiro的处理和springboot的处理顺序不同,导致我们构造的poc在shiro侧理解的是访问的/test/,/test/我们本身就没有限制权限,放过了这个原本需要认证权限的请求,而springboot侧则是访问的是/test/;name,然后springboot把;name当做一个字符串去寻找对应的路由,返回了对应的字符串。
漏洞复现¶
正常请求如下所示
7.jpg
8.jpg
构造恶意请求
test/%3b
{name}
9.jpg