CVE-2022-22978

https://github.com/vulhub/vulhub/tree/master/spring/CVE-2022-22978

概述

Spring Security Authorization Bypass in RegexRequestMatcher

在Spring Security中使用RegexRequestMatcher且规则中包含带点号的正则表达式时,攻击者可以通过构造恶意数据包绕过身份认证

影响版本

Spring Security ≤ 5.5.6/5.6.3

分析

使用代码来跟一下分析一下。

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception{
        httpSecurity.authorizeRequests().regexMatchers("/admin/.*").authenticated();
    }
}

进入 regexMatchers 看一下,正则字符串的数据走向

org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry#regexMatchers(java.lang.String...)

org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry.RequestMatchers#regexMatchers(org.springframework.http.HttpMethod, java.lang.String...)

org.springframework.security.web.util.matcher.RegexRequestMatcher#RegexRequestMatcher(java.lang.String, java.lang.String)

org.springframework.security.web.util.matcher.RegexRequestMatcher#RegexRequestMatcher(java.lang.String, java.lang.String, boolean)

java.util.regex.Pattern#compile(java.lang.String, int)

通过上面的路径可以看到,设置的 pattern 一路进入到 RegexRequestMatcher,然后使用 Pattern.compile 进行解析,但是注意一下这里传入的 flags,因为 caseInsensitive 写死是 false,所以传入的 flag 是 DEFAULT,这里可以看到是 0。

光这样看可能不清楚有什么问题,搜索一下传入的 flags 是干什么用的。

在Java的`Pattern.compile`方法中,参数`flags`是一个用于设置正则表达式匹配的一些选项的标志位。这些标志位可以修改正则表达式的行为,使其更适应特定的匹配需求。您可以将多个标志位使用按位或(`|`)操作符组合在一起。

以下是一些常用的标志位及其用途:

1. **`Pattern.CASE_INSENSITIVE`:** 忽略大小写匹配。例如,正则表达式中的字母字符会与目标字符串中的大写和小写字母字符进行匹配。

2. **`Pattern.MULTILINE`:** 启用多行模式。在多行模式下,`^`和`$`元字符会分别匹配行的开始和结束,而不仅仅是整个字符串的开始和结束。

3. **`Pattern.DOTALL`:** 启用`.`匹配所有字符,包括换行符。在默认情况下,`.`匹配除了换行符外的所有字符。

4. **`Pattern.UNICODE_CASE`:** 启用Unicode感知的大小写折叠。这对于处理不同语言的字符串非常有用,可以正确地处理特定语言的大小写规则。

5. **`Pattern.COMMENTS`:** 允许在正则表达式中使用空格和注释,使正则表达式更易读。

6. **`Pattern.UNIX_LINES`:** 在此模式下,只有`\n`被认为是行结束符。默认情况下,`\r\n`、`\r`和`\n`都被认为是行结束符。

7. **`Pattern.CANON_EQ`:** 在Unicode规范化的情况下启用规范等价匹配。

这些标志位可以通过按位或操作来组合,例如:

```java
Pattern pattern = Pattern.compile("regex", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
```

这将创建一个正则表达式模式,同时启用了大小写不敏感和多行模式。

通过选择适当的标志位,您可以更好地控制和定制正则表达式的匹配行为,以满足您的特定需求。

漏洞版本传入的是0,也就是默认情况,在默认情况下,`.`匹配除了换行符外的所有字符,也就是说换行符可以绕过包含`.`的正则。

修复分析

在修复代码中可以看到 DEFAULT 的值改成了Pattern.DOTALL,也就是`.`会匹配所有的字符。