(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

参考链接

https://www.anquanke.com/post/id/214964#h2-2