CVE-2022-22978 SpringSecurity权限绕过

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-22978

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1678810724-image-20230129155429-u6tweg9.png

从上面的漏洞通告得知,SpringSecurity组件中RegexRequestMatcher组件存在权限绕过问题且漏洞组件版本存在于5.5.6 和 5.6.3 以及不受支持的旧版本中

pom相关依赖即指定springsecurity为漏洞版本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
    <properties>
        <java.version>1.8</java.version>
        <spring-security.version>5.5.6</spring-security.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
    </dependencies>

添加相关controller

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package com.example.springbootbasestudy.controller;

import com.example.springbootbasestudy.pojo.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloController {

    @ResponseBody
    @RequestMapping("/helloworld/*")
    public String hello(){
        return "hello world!~";
    }
}

使用RegexRequestMatcher对访问请求进行拦截

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package com.example.springbootbasestudy.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.util.matcher.RegexRequestMatcher;

@Configuration
public class Security extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().requestMatchers(new RegexRequestMatcher("/helloworld/.*",null)).authenticated();
    }
}

存在漏洞版本的SpringSecurity组件版本中将给定的正则表达式编译为带有给定标志的模式设置为default

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1678810725-image-20230129203015-h70rujs.png

查看相关文档,共有如下标志位

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1678810725-image-20230129203148-y2sdlr0.png

  • CASE_INSENSITIVE

    • 1
      
      public static final int CASE_INSENSITIVE
      

      启用不区分大小写的匹配。默认情况下,不区分大小写的匹配假定仅匹配US-ASCII字符集中的字符。 可以通过与此标志一起指定UNICODE_CASE``标志来启用Unicode感知不区分大小写的匹配。

      也可以通过嵌入式标志表达式(?i)启用不区分大小写的匹配。

      指定此标志可能会造成轻微的性能损失。

  • COMMENTS

    • 1
      
      public static final int COMMENTS
      

      允许空格和注释格式。在此模式下,将忽略空格,并且以#开头的嵌入式注释将被忽略,直到行尾。

      注释模式也可以通过嵌入式标志表达式(?x)启用 。

  • MULTILINE

    • 1
      
      public static final int MULTILINE
      

      启用多行模式。在多行模式下,表达式^和$分别匹配行终止符或输入序列的结尾。 默认情况下,这些表达式仅在整个输入序列的开头和结尾匹配。

      也可以通过嵌入式标志表达式(?m)启用多模式模式。

  • LITERAL

    • 1
      
      public static final int LITERAL
      

      启用模式的文字解析。当指定此标志时,指定模式的输入字符串将被视为文字字符序列。 输入序列中的元字符或转义序列将没有特殊的含义。

      CASE_INSENSITIVE和UNICODE_CASE标志在与此标志一起使用时保持对匹配的影响。 其他旗帜变得多余。

      没有嵌入的标志字符用于启用文字解析。

      从以下版本开始:1.5

  • DOTALL

    • 1
      
      public static final int DOTALL
      

      启用点阵模式。在dotall模式下,表达式.匹配任何字符,包括行终止符。 默认情况下,此表达式与行终止符不匹配。

      Dotall模式也可以通过嵌入式标志表达式(?s)启用 。 ( s是“单行”模式的助记符,这在Perl中被称为)。

  • UNICODE_CASE

    • 1
      
      public static final int UNICODE_CASE
      

      启用Unicode感知案例折叠。当指定此标志时,不区分大小写的匹配(由CASE_INSENSITIVE``​​标志启用)以与Unicode标准一致的方式完成。 默认情况下,不区分大小写的匹配假定仅匹配US-ASCII字符集中的字符。

      Unicode感知案例折叠也可以通过嵌入式标志表达式(?u)启用 。

      指定此标志可能会造成性能损失。

  • CANON_EQ

    • 1
      
      public static final int CANON_EQ
      

      实现规范等价。当指定这个标志时,两个字符将被认为是匹配的,只有当他们的完整的规范分解符合时才匹配。 表达"a\u030A",例如,将指定该标志时,该字符串"\u00E5"匹配。 默认情况下,匹配不考虑规范等价。

      没有嵌入的标志字符用于启用规范等效。

      指定此标志可能会造成性能损失。

  • UNICODE_CHARACTER_CLASS

    • 1
      
      public static final int UNICODE_CHARACTER_CLASS
      

      启用Unicode版本的预定义字符类POSIX字符类 。当指定此标志时,(仅US-ASCII) 预定义字符类POSIX字符类符合*Unicode Technical Standard #18: Unicode Regular Expression* 附件C:兼容性属性

      也可以通过嵌入式标志表达式(?U)启用UNICODE_CHARACTER_CLASS模式。

      该标志意味着UNICODE_CASE,也就是说,它可以支持Unicode感知案例折叠。

      指定此标志可能会造成性能损失。

      从以下版本开始:1.7

当使用默认匹配模式且存在 .​ 匹配符时,可以通过\n \r 对匹配内容进行绕过

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1678810725-image-20230129204216-4kgg1lh.png

注:正则中.​匹配除 \n \r之外的单个字符

场景换为开启的web服务,没权限的情况下访问会被拦截

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1678810725-image-20230129201849-elf2jlg.png

通过\r \n 成功绕过拦截

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1678810725-image-20230129201819-66eiad0.png

官方补丁如下

https://github.com/spring-projects/spring-security/compare/5.6.3...5.6.4

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1678810725-image-20230129204958-4srbdws.png

将默认匹配模式指定为DOTALL(匹配任何字符)​,本地指定DOTALL​模式对含\n \r的payload成功匹配,即无法绕过

https://mtnsmdbt.oss-cn-hangzhou.aliyuncs.com/blog/1678810725-image-20230129205225-ki0k857.png