menu arrow_back 湛蓝安全空间 |狂野湛蓝,暴躁每天 chevron_right All_wiki chevron_right yougar0.github.io(基于零组公开漏洞库 + PeiQi文库的一些漏洞)-20210715 chevron_right Web安全 chevron_right Apache Shiro chevron_right (CVE-2020-13933)Apache Shiro _ 1.6.0 身份认证绕过漏洞.md
  • home 首页
  • brightness_4 暗黑模式
  • cloud
    xLIYhHS7e34ez7Ma
    cloud
    湛蓝安全
    code
    Github
    (CVE-2020-13933)Apache Shiro _ 1.6.0 身份认证绕过漏洞.md
    3.23 KB / 2021-04-21 09:23:46
        (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
    
    
    links
    file_download