目录

继续梳理shiro历史漏洞

目录

su18后面没再更新了,所以我们继续写。

CVE-2020-17510

漏洞信息

漏洞信息 详情
漏洞编号 CVE-2020-17510
影响版本 shiro < 1.7.0
漏洞描述 Apache Shiro 由于处理身份验证请求时存在权限绕过漏洞,远程攻击者可以发送特制的HTTP请求,绕过身份验证过程并获得对应用程序的未授权访问。
漏洞关键字 Spring | 顺序 | %2e | 绕过
漏洞补丁 Commit-16fc47a
相关链接 https://security.snyk.io/vuln/SNYK-JAVA-ORGAPACHESHIRO-1050098

漏洞分析

条件

  1. springboot version >= 2.3.1.RELEASE

访问/hello/%2e绕过限制 shiro的流程:解码->/hello/.->路径标准化->/hello/绕过限制 sprinboot会使用全路径,/hello/%2e可以匹配到/hello/{name}

/%2e
/%2e/
/%2e%2e
/%2e%2e/

下面的呢?
/.
/./
/..
/../

漏洞修复

当升级版本为1.7.0的时候需如果没使用shiro-spring-boot-web-starter要额外配置[ShiroRequestMappingConfig](https://shiro.apache.org/spring-framework.html#web_applications)如果没配置,仍然有绕过的问题。

@Configuration
@Import({ShiroRequestMappingConfig.class})
public class ApplicationConfig {
}

ShiroRequestMappingConfig内部注册了ShiroUrlPathHelper,强制将spring对url的判断逻辑变为shiro的了。这样就不会出现二者的差异

@Configuration
public class ShiroRequestMappingConfig {
    public ShiroRequestMappingConfig(RequestMappingHandlerMapping requestMappingHandlerMapping) {
        requestMappingHandlerMapping.setUrlPathHelper(new ShiroUrlPathHelper());
    }
}

之前关于spring版本不同引起的是否全路径问题。之前高版本是使用全路径的。

public class ShiroUrlPathHelper extends UrlPathHelper {

    @Override
    public String getPathWithinApplication(HttpServletRequest request) {
        return WebUtils.getPathWithinApplication(request);
    }

    @Override
    public String getPathWithinServletMapping(HttpServletRequest request) {
        return WebUtils.getPathWithinApplication(request);
    }
}

CVE-2020-17523

漏洞详情

漏洞信息 详情
漏洞编号 CVE-2020-17510
影响版本 shiro < 1.7.1
漏洞描述 Shiro 1.7.1 之前的版本,在将 Shiro 与 Spring 结合使用时,特制的 HTTP 请求可能会导致身份验证绕过。
漏洞关键字 Spring | 顺序 | %20 | 绕过
漏洞补丁 Commit-ab1ea4a
相关链接 https://tttang.com/archive/1645/#toc_cve-2020-17510

漏洞分析

AntPathMatcher在匹配path和pattern的时候会将二者的空格都trim掉 这样匹配/hello//hello/*就等于/hello//hello*,匹配为false,绕过权限。 同时spring没有去掉空格,所以可以匹配到/hello/{name}官方给出的一些tr

漏洞修复

AntPathMatcher增加参数false和true,第三个参数代表是否要trimTokens,改为false。

public static String[] tokenizeToStringArray(String str, String delimiters, boolean trimTokens, boolean ignoreEmptyTokens) {
...
                if (trimTokens) {
                    token = token.trim();
                }
}

CVE-2021-41303

漏洞详情

漏洞信息 | 详情 |
--- | --- |
漏洞编号 | CVE-2021-41303/ NVD-2021-41303 |
影响版本 | shiro < 1.8.0 |
漏洞描述 | 1.8.0 之前的 Apache Shiro,在 Spring Boot 中使用 Apache Shiro 时,特制的 HTTP 请求可能会导致身份验证绕过。用户应该更新到 Apache Shiro 1.8.0。 |
漏洞关键字 | |
漏洞补丁 | Commit-4a20bf0 |
相关链接 | https://threedr3am.github.io/2021/09/22/ |

漏洞分析

如下,requestURINoTrailingSlash是我们的请求本身去掉末尾反斜杠。 在else分支获取过滤链的时候使用的filterChainManager.proxy内部是去我们的filterMap里根据key获取相应的filter,而传入这个key根本就不是我们配置的而是requestURINoTrailingSlash所以一定会抛异常。

public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) {
    FilterChainManager filterChainManager = getFilterChainManager();
    if (!filterChainManager.hasChains()) {
        return null;
    }

    final String requestURI = getPathWithinApplication(request);
    final String requestURINoTrailingSlash = removeTrailingSlash(requestURI);

    //the 'chain names' in this implementation are actually path patterns defined by the user.  We just use them
    //as the chain name for the FilterChainManager's requirements
    for (String pathPattern : filterChainManager.getChainNames()) {
        // If the path does match, then pass on to the subclass implementation for specific checks:
        if (pathMatches(pathPattern, requestURI)) {
            if (log.isTraceEnabled()) {
                log.trace("Matched path pattern [{}] for requestURI [{}].  " +
                        "Utilizing corresponding filter chain...", pathPattern, Encode.forHtml(requestURI));
            }
            return filterChainManager.proxy(originalChain, pathPattern);
        } else {

            // in spring web, the requestURI "/resource/menus" ---- "resource/menus/" bose can access the resource
            // but the pathPattern match "/resource/menus" can not match "resource/menus/"
            // user can use requestURI + "/" to simply bypassed chain filter, to bypassed shiro protect

            pathPattern = removeTrailingSlash(pathPattern);

            if (pathMatches(pathPattern, requestURINoTrailingSlash)) {
                if (log.isTraceEnabled()) {
                    log.trace("Matched path pattern [{}] for requestURI [{}].  " +
                              "Utilizing corresponding filter chain...", pathPattern, Encode.forHtml(requestURINoTrailingSlash));
                }
                // 如下根据请求路径去map里拿,根本拿不到,所以会抛异常,在后面加一个
                return filterChainManager.proxy(originalChain, requestURINoTrailingSlash);
            }
        }
    }

    return null;
}

根据官方修复的Test可以猜测出(加上threedr3am给出的文章) 我们一定是配置了如下两个配置

map.put("/m4ra7h0n/*/book", "authc");
map.put("/m4ra7h0n/hacker/book", "anon");

其中第一个是范围匹配,而下面的是特例,允许访问的。我们的请求访问的是/m4ra7h0n/hacker/book/执行到上面过滤链的时候由于AntPathMatcher的匹配特性和/m4ra7h0n/hacker/book/不匹配,于是进入else分支,else则去拿去掉反斜杠后的/m4ra7h0n/hacker/book//m4ra7h0n/hacker/book,拿到第二条过滤链,从而绕过第一条的限制。

漏洞修复

如下,替换掉requestURINoTrailingSlash

CVE-2022-32532

漏洞详情

漏洞信息 | 详情 |
--- | --- |
漏洞编号 | CVE-2021-41303/ NVD-2021-41303 |
影响版本 | shiro < 1.9.1 && spring >=5.3.2 |
漏洞描述 | 在1.9.1之前的Apache Shiro中,RegexRequestMatcher可能会被错误配置,从而在某些servlet容器上被绕过。应用程序使用RegExPatternMatcher与.的正则表达式可能容易被授权绕过。 |
漏洞关键字 | |
漏洞补丁 | Commit-6bcb92e |
相关链接 | 被4ra1n删了 |

漏洞分析

Apache Shiro < 1.9.1 springboot有限制,低版本无法匹配\n\r 官方解决这个bug的版本是spring 5.3.2 https://github.com/spring-projects/spring-framework/issues/23252

我觉得他在模仿spring中的漏洞https://xz.aliyun.com/t/11473

总的来说,就是4ra1n使用shiro中另一个path matcher,RegexRequestMatcher,他只有一个match方法,并且match之前没有设置Pattern.compile(regex,Pattern.DOTALL);这就导致了shiro在匹配带有\n\r时匹配失败。 他在shiro中pattern为(regex匹配方式):/m4ra7h1n/.* spring controller为:/m4ra7h1n/{name} 然后访问的时候加上%0a``%0d等字符绕过shiro匹配 同时spring匹配需要版本>=5.3.2

漏洞修复

RegexRequestMatcher修复了内部的Pattern.compile,增加Pattern.DOTALL

CVE-2023-22602

漏洞详情

漏洞信息 | 详情 |
--- | --- |
漏洞编号 | NVD-2023-22602 |
影响版本 | shiro < 1.11.0 & Spring Boot >= 2.6 |
漏洞描述 | 当使用1.11.0之前的Apache Shiro和Spring Boot 2.6+时,一个特殊制作的HTTP请求可能会导致身份验证绕过。 |
漏洞关键字 | |
漏洞补丁 | Commit-e167a71 |
相关链接 | https://forum.butian.net/share/2118 |

shiro配置如下

DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
chainDefinition.addPathDefinition("/login.html", "authc"); // need to accept POSTs from the login form
chainDefinition.addPathDefinition("/logout", "logout");
chainDefinition.addPathDefinition("/admin/**", "roles[admin]");
chainDefinition.addPathDefinition("/guest/**", "roles[guest]");

controller如下

@Controller
public class AccountInfoController {
    @RequestMapping("/admin/**")
    public String home(Model model) {
        String name = "World";
        Subject subject = SecurityUtils.getSubject();
        PrincipalCollection principalCollection = subject.getPrincipals();
        if (principalCollection != null &amp;&amp; !principalCollection.isEmpty()) {
            name = principalCollection.getPrimaryPrincipal().toString();
        }
        model.addAttribute("name", name);
        return "account-info";
    }

shiro解析..后绕过防护, spring 不解析则可以匹配。

漏洞分析

spring匹配访问路径和controller配置路径的默认匹配器变更。当Spring版本>=5.3.0时org.springframework.web.servlet.mvc.method.RequestMappingInfo#getMatchingCondition()中Url匹配模式直接从PatternsCondition.getMatchingCondition();转变成了PathPatternsRequestCondition.getMatchingCondition(),这会导致其使用ServletRequestPathUtils.getParsedRequestPath(request).pathWithinApplication();查找url,未处理跨目录。

@Override
@Nullable
public RequestMappingInfo getMatchingCondition(HttpServletRequest request) {
  ....  
    // default
    PathPatternsRequestCondition pathPatterns = null;
    if (this.pathPatternsCondition != null) {
    pathPatterns = this.pathPatternsCondition.getMatchingCondition(request);
    if (pathPatterns == null) {
          return null;
    }
    }
    
    PatternsRequestCondition patterns = null;
    if (this.patternsCondition != null) {
       patterns = this.patternsCondition.getMatchingCondition(request);
       if (patterns == null) {
          return null;
       }
    }
}

根据文档:https://docs.spring.io/spring-boot/docs/current/reference/html/web.html#web.servlet.spring-mvc.content-negotiation spring framework 5.3(springboot2.6)之后默认使用PathPatternParser策略,替代AntPathMatcher策略 更详细的文档,建议看一下 https://spring.io/blog/2020/06/30/url-matching-with-pathpattern-in-spring-mvc

漏洞修复

https://github.com/apache/shiro/commit/e167a712d6908be2a5c5f2c36fc10ab64a4b256a 更改默认使用ant_path_matcher,而不是spring5.3.0更新版本后默认使用path_pattern_parser

CVE-2023-34478

漏洞详情

漏洞信息 | 详情 |
--- | --- |
漏洞编号 | CVE-2023-34478/NVD-2023-34478 |
影响版本 | shiro < 1.12.0 |
漏洞描述 | shiro < 1.12.0对于类似目录穿越的请求,在非springframework特定的场景下可能存在权限绕过的可能 |
漏洞关键字 | |
漏洞补丁 | Commit-c3ede3f |
相关链接 | https://forum.butian.net/share/2380 |

漏洞分析

这次场景从springframework转到非springframework中了使用的是Jersey 总感觉有点牵强,但是漏洞评分给了9.8分,因为他可能影响更多的组件。 原理是利用shiro可以解析..而Jersey不解析..的原理。和CVE-2023-22602是类似的。

漏洞修复

InvalidRequestFilter中添加了请求中对.``/./``/.``%2f%2e的过滤,如果有相关输入,则验证失败。 模仿spring security中的过滤 org.springframework.security.web.firewall.StrictHttpFirewall

拦截内容 |
--- |
分号(;或者%3b或者%3B) |
斜杠(%2f或者%2F) |
反斜杠(\或者%5c或者%5C) |
%25(URL编码了的百分号%) |
英文句号.(%2e或者%2E) |

总结

根据CVE-2020-1957,CVE-2023-22602我发现了两个其他组件的漏洞,大家可自行尝试。 同时我发觉,翻文档的能力一定要很强,cve的挖掘,本质上也是信息搜集。