CVE-2022-22978 Spring-Security 漏洞复现

CVE-2022-22978 Spring-Security 漏洞复现

1 说明

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

2 环境搭建

环境搭建地址可以参考如下的github 工程:https://github.com/DeEpinGh0st/CVE-2022-22978

3 漏洞复现

  1. 正常访问环境信息

  1. 通过%0a绕过访问限制

可以看到通过%0a绕过了spring security的用户鉴权

4 漏洞分析

4.1 源码对比

  1. 从github上拉取工程,拉取工程的地址为:https://github.com/DeEpinGh0st/CVE-2022-22978
  2. 参考官网的修改方案:https://github.com/spring-projects/spring-security/commit/70863952aeb9733499027714d38821db05654856

  • Pattern 类是 java.util.regex 包的三个类之一,负责处理正则表达式相关
  • Pattern.DOTALL:表示更改.的含义,使它与每一个字符匹配(包括换行符\n),默认情况下, 正则表达式中点(.)不会匹配换行符, 设置了Pattern.DOTALL模式, 才会匹配所有字符包括换行符。
  • Pattern.CASE_INSENSITIVE:忽略大小写。

从代码上看:可以看到RegexRequestMatcher.java文件的修复是增加了对换行符的匹配以及忽略大小写。

接着看下对应的测试代码

RegexRequestMatchertests.java文件也给了绕过的提示(\r的URl编码为%0d,\n的URL编码为%0a)。

4.2 查看java 正则说明

  1. 查看java doc 关于pattern的说明:https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#DOTALL

    DoTALL 说明

  • DOTALL

    public static final int DOTALL
    

    Enables dotall mode.

    在dotall模式中,表达式.匹配任何字符,包括行结束符。默认情况下,此表达式不匹配行终止符。

    也可以通过嵌入的标志表达式(?s),启用点所有模式。(s是“单行”模式的助记符,在Perl中这么说。)

  • UNICODE_CASE

    public static final int UNICODE_CASE
    

    Enables Unicode-aware case folding.

    如果指定了该标志,则在通过case_sensitive标志启用时,将以与Unicode标准一致的方式进行不区分大小写的匹配。默认情况下,不区分大小写的匹配假设仅匹配US-ASCII字符集中的字符。

    还可以通过嵌入标志表达式(?u)启用Unicode感知的大小写折叠。

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

​ 从上述的doc的说明,可以查出,对于默认的Pattern模式,不开启DOTALL时候,在默认匹配的时候不会匹配\r \n 字符。

  1. 对比spring security的修改代码

    public final class RegexRequestMatcher implements RequestMatcher {
    private static final int DEFAULT = Pattern.DOTALL;
    
    private static final int CASE_INSENSITIVE = DEFAULT | Pattern.CASE_INSENSITIVE;
    
    private static final Log logger = LogFactory.getLog(RegexRequestMatcher.class);
    
    @@ -68,7 +70,7 @@ public RegexRequestMatcher(String pattern, String httpMethod) {
     * {@link Pattern#CASE_INSENSITIVE} flag set.
     */
    public RegexRequestMatcher(String pattern, String httpMethod, boolean caseInsensitive) {
    	this.pattern = Pattern.compile(pattern, caseInsensitive ? CASE_INSENSITIVE : DEFAULT);
    	this.httpMethod = StringUtils.hasText(httpMethod) ? HttpMethod.valueOf(httpMethod) : null;
    }
    

​ 此修改已经默认开启了DOTALL,所有的字符都会对比。

4.3 漏洞说明

因此该漏洞主要是因为在正则匹配的时候产生的问题,由于匹配的模式选择的问题,导致了该漏洞。下面写个代码验证下

  • 使用默认的正则

该正则默认模式,显示的结果为正则不匹配

  • 正则开启DOTALL模式

​ 开启DOTALL模式,正则显示匹配

4.4 漏洞分析

回过头来看下存在漏洞的代码

在匹配的时候只要输入url 为:/admin/111\n 即可绕过url限制,因为和/admin/.*不匹配,因此绕过了鉴权。

Refer

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

2.https://nosec.org/home/detail/5006.html

posted @ 2022-09-03 14:38  TT0TT  阅读(2105)  评论(0编辑  收藏  举报