文章摘要
TianliGPT
生成中...

本文最后更新于 2024-10-09,文章内容可能已经过时。

Spring-security与Apache Shiro认证绕过漏洞复现

Spring-security (CVE-2022-22978) 与 Apache Shiro (CVE-2022-32532) 认证绕过漏洞

一、两者的关系

Spring Security RegexRequestMatcher(CVE-2022-22978)认证绕过漏洞Apache Shiro RegExPatternMatcher(CVE-2022-32532)认证绕过漏洞,这二者原理本质上来说都是一致的,都是在使用RegexRequestMatcherRegExPatternMatcher 进行认证配置时,正则表达式中含有’ . ',攻击者可以通过构造特殊请求绕过正则表达式检查,进而实现认证绕过。

二、Spring-security(CVE-2022-22978) 漏洞

2.1 漏洞简介

当 Spring-security 使用 RegexRequestMatcher 进行权限配置,由于RegexRequestMatcher正则表达式配置权限的特性,正则表达式中包含“.”时,未经身份验证攻击者可以通过构造恶意数据包绕过身份认证。

影响版本:

  • Spring Security 5.5.x < 5.5.7

  • Spring Security 5.6.x < 5.6.4

2.2 漏洞分析

image-20241009195836842

image-20241009195904484

这里我们创建一个简单的Spring Boot项目进行分析,在IDEA中新建一个带 Spring Security 的 Spring Boot 项目,而后修改版本使用 5.6.3版本。

<properties>
    <spring-security.version>5.6.3</spring-security.version>
</properties>
XML

​ 完成创建后,新建一个 Controller (AdminController)。此Controller在当用户访问 /admin 下任意页面时,返回一个字符串 “hello administrator”

@RestController
public class AdminController {
    @GetMapping("/admin/*")
    public String toAdmin(){
        return "hello administrator!";
    }
}
Java

​ 再添加一个简单的认证配置SecurityConf,如下:

@Configuration
public class SecurityConf extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception{
        http.authorizeRequests().regexMatchers("/admin/.*").authenticated();
    }
}
Java

image-20241009200758128

整体的pom.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>  //这个版本一定要高
    </parent>

    <groupId>org.example</groupId>
    <artifactId>springsecurity</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <spring-security.version>5.6.3</spring-security.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!-- web模块 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>
XML

相关函数说明如下:

  • authorizeRequests():使用这个方法进行url授权操作,对url进行访问权限控制。
  • regexMatchers():进行正则匹配,匹配访问路径。
  • authenticated():访问控制方法,规定所有匹配到的路径需经过认证才能访问。

​ 这里的用于匹配的正则表达式为" /admin/.* ",通过前面漏洞简介我们知道使用的正则表达式中含有" . “就有可能造成认证绕过,所以此处使用” .* ",该正则表示匹配 /admin/下所有路径,当用户访问/admin/的任意页面时,都是需要认证后才能访问。

​ 启动项目,访问 http://localhost:8080/admin/123 ,发现访问失败,响应 403。说明认证配置成功,只有认证通过的用户才能访问 /admin/ 下的页面。

image-20221025114421324

此次漏洞主要是在 RegexRequestsMatcher 这个类中 ,当用户访问页面时,会判断访问的页面是否需要认证,而 Spring Security 使用 RegexRequestsMatcher 对 URL 进行正则匹配。**而它使用 matches() 方法对 URL 进行匹配,所以我们将断点打在此处。**可以看到使用上述url访问时,正则匹配成功,确定其访问的是 /admin/ 下的资源。

进入org.springframework.security.web.util.matcher.RegexRequestMatcher的matches()方法中。重启项目,进入debug模式,页面输入urlhttp://localhost:8080/admin123重新访问

当debug选中某一行的时候,按快捷键 Alt + F8 就可以打开Evaluate计算表达式窗口

​ 接着使用 http://localhost:8080/admin/ 123 或者 http://localhost:8080/admin/ 123 进行认证绕过,这里的 %0a 与 %0d 分别是url编码后的换行符" \n “、回车符” \r ",因为在 RegexRequestsMatcher 中进行对应路径匹配的正则表达式中的" . "默认情况不会匹配换行符与回车符,所以这里会匹配失败。这样 Spring Security 会认为用户并没有访问 /admin/ 下的资源,所以用户不需要认证即可访问。

image-20241009212413665

​ 最终用户通过这种方式,绕过认证,直接访问到 /admin 下的页面。

image-20241009212440372

2.3 漏洞复现

​ 此次漏洞复现过程比较简单,就不过多赘述。可以使用docker拉取镜像简单复现即可,搭建过程如下。

docker环境:s0cke3t/cve-2022-22978

环境搭建:

docker pull s0cke3t/cve-2022-22978
docker run -itd --name=cve-2022-22978 -p 8080:8080 docker.io/s0cke3t/cve-2022-22978:latest
Bash

搭建完成后访问结果如下:

image-20241009213841230

输入页面上提供的payload:

http://192.168.91.128:8080/admin/index%0a 
Perl

image-20241009213953947

成功访问到管理界面。

2.4 补丁分析

​ 参考官方发布的5.6.3与5.6.4版本比较说明(https://github.com/spring-projects/spring-security/compare/5.6.3...5.6.4),看到 RegexRequestsMatcher 版本变化如下:

image-20221025151609388

​ 修改了第46行与71行,其中关键字说明如下:

  • Pattern:位于 java.util.regex.Pattern.java,是 regex 下三个处理正则表达式相关类之一。

  • Pattern.DOTALL:用于更改正则中" . "的含义,使其能够匹配任意字符(包括换行符\n与回车符\r),默认情况下,正则表达式 " . " 不会匹配换行符。

  • Pattern.CASE_INSENSITIVE:表示忽略大小写。

​ 结合前面的漏洞分析,我们可以知道其使用相关参数配置,增加了对换行符的匹配以及忽略大小写以此来防止绕过。

2.5 修复建议

更新为已修复漏洞的版本。

Spring Security 5.5.x升级至5.5.7 (https://github.com/spring-projects/spring-security/releases/tag/5.5.7 )。

Spring Security 5.6.x升级至5.6.4 (https://github.com/spring-projects/spring-security/releases/tag/5.6.4)。

三、Apache Shiro(CVE-2022-32532)漏洞

3.1 漏洞简介

​ 2022年6月 Apache Shiro 官方发布了 Apache Shiro 1.91版本,其中修复了之前版本的一个身份认证绕过漏洞(CVE-2022-32532),RegexRequestMatcher 可能被错误配置为在某些 servelet 容器上绕过,当使用 RegExPatternMatcher 的应用程序在正则表达式中使用”.”时,可以通过构造恶意数据包绕过身份认证,导致系统配置的权限验证失效。

影响版本:

Apache Shiro < 1.9.1

3.2 漏洞分析

​ 这里使用漏洞提交者 4ra1n 的演示项目进行简单分析。

https://github.com/Lay0us/CVE-2022-32532

​ 查看项目源码,作者定义了 DemoController,当用户访问 /permit 下任意页面时,返回一个字符串 “ success! ”

image-20241009215333946

​ 作者自定义了一个 AccessControlFilter 实现类 MyFilter ,用于访问控制,其中指定使用 RegExPatternMatcher 来进行路径的正则匹配。在其中还覆写了 isAccessAllowed() 方法和 onAccessDenied() 方法,前者用于检测是否认证成功,若请求头中含有token字段且为‘4ra1n’,则认证成功。后者为认证失败后,返回拒绝访问给用户。

image-20241009215323003

​ 而 RegExPatternMatcher 中也是使用了 java.util.regex的 Pattern 类的 compile() 进行正则匹配

image-20241009215440911

​ MyShiroFilterFactoryBean类中接着定义继承自ShiroFilterFactoryBean类的 MyShiroFilterFactoryBean,添加刚才创建好的 MyFilter 并设置匹配规则为" /permit/.* " 字符串,表示拦截 /permit/ 下所有的路径。

image-20241009215607242

​ 我们在浏览器中输入 http://localhost:8080/permit/123 ,进行访问,因为这里我们直接访问,请求头部中并没有添加token字段,所以会认证失败,前端返回 " access denied "(认证失败)。

image-20241009215651230

​ 同理我们将断点设置在 RegExPatternMatcher 的 matches() 方法中,重启debug,当我们使用前面的url http://localhost:8080/permit/123访问时,可以看到正则匹配成功。

image-20241009215936358

​ 而使用 http://localhost:8080/permit/ 123 访问时,正则匹配失败,这跟 CVE-2022-22978 漏洞触发机制一致。

image-20241009220046222

​ 最后用户通过这种方式,绕过认证,直接访问到 /permit/ 下的页面。

image-20241009220123695

3.3 漏洞复现

​ 该漏洞与前面的CVE-2022-22978漏洞原理本质上一致,复现过程也十分简单,就不过多演示了。可以使用docker创建漏洞环境容器复现,这里使用 vulfocus 上对应的靶场进行复现(vulfocus/shiro-cve_2022_32532),搭建过程如下:

docker pull vulfocus/shiro-cve_2022_32532
docker run -itd --name=cve-2022-32532 -p 8080:8080 docker.io/vulfocus/shiro-cve_2022_32532:latest
Bash

image-20241009220451414

直接输入payload的url进行访问:成功访问管理界面

image-20241009220543714

3.4 补丁分析

​ 参考官方提交的shiro补丁(https://github.com/apache/shiro/commit/6bcb92e06fa588b9c7790dd01bc02135d58d3f5b),发现其修复方式和 CVE-2022-22978 修复方式一样,配置了相关参数,增加了对换行符的匹配以及忽略大小写以此来防止绕过。

image-20221025165955865

3.5 修复建议

  1. 更新版本为新版已修复漏洞的版本。

参考文章

  1. CVE-2022-22978 Spring-security 认证绕过漏洞(https://zhuanlan.zhihu.com/p/562074166)。

  2. Spring Security RegexRequestMatcher 认证绕过漏洞分析(CVE-2022-22978)(https://nosec.org/home/detail/5006.html)。

  3. 浅谈Shiro CVE-2022-32532(http://www.hackdig.com/06/hack-703460.htm)。