前言
无。
漏洞复现
要求版本:shiro<1.6.0,测试用的代码不变。
与CVE-2020-1957相似,在路径后加上URL编码后的分号;,即%3b就可以绕过认证:
漏洞分析
经过几个小版本的修改,此时的getPathWithinApplication函数如下:
public static String getPathWithinApplication(HttpServletRequest request) {
return normalize(removeSemicolon(getServletPath(request) + getPathInfo(request)));
}
private static String removeSemicolon(String uri) {
int semicolonIndex = uri.indexOf(';');
return (semicolonIndex != -1 ? uri.substring(0, semicolonIndex) : uri);
}
使用getServletPath函数从tomcat中获取路径,结果在tomcat中会经过一次URL解码,为/admin/;admin:
然后使用removeSemicolon函数截断分号;,再用normalize标准化,最后的返回结果就是/admin/:
再被去掉末尾的/,在doMatch函数就匹配不上了,就绕过了认证。
将分号URL编码可以让tomcat不会对分号做处理,这样到了spring的部分就不会出现404。
漏洞修复
在1.6.0版本中再访问,会出现400:
通过调试可以看到,在匹配不到filter时,getChain函数会使用默认的InvalidRequestFilter:
其中会经过其isAccessAllowed函数来判断该请求是否合法:
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
String uri = WebUtils.toHttp(request).getRequestURI();
return !containsSemicolon(uri)
&& !containsBackslash(uri)
&& !containsNonAsciiCharacters(uri);
}
简单来说就是不能包含分号、反斜杠和非ASCII字符(虽然这里的uri是没经过URL解码的,但是这两个contains函数里面把字符跟他们的URL编码,包括大小写形式都ban了。非ASCII字符虽然没有做URL编码的处理,但是好像也没什么用法了)。