
Spring Security의 RegexRequestMatcher에서 CVE-2022-22978 권한 부여 우회에 대한 단계별 시연으로, 취약한 앱 설정, 페이로드 실행 및 수정 검증을 포함합니다.
제가 조사한 정보에 따르면, 이는 Spring Security 프레임워크의 RegexRequestMatcher 클래스와 관련된 취약점입니다. 구체적으로, 정규 표현식에 마침표(.)가 포함된 RegexRequestMatcher를 사용하는 애플리케이션은 \r(%0a), \n(%0d) 문자를 이용해 우회될 수 있으며, 이를 통해 공격자는 인증 없이 허용되지 않은 경로에 접근할 수 있습니다.
취약한 Spring Security 프레임워크 버전:
5.5.7 이전의 5.5.x5.6.4 이전의 5.6.x이 취약점을 정적으로 분석하기 위해 Spring Security 소스 코드를 확인해야 합니다. 구체적으로, GitHub에서 취약한 버전 5.6.3과 수정된 버전 5.6.4 사이의 커밋 비교 기능을 사용했습니다. 다음 링크를 참조하세요: Comparing 5.6.3...5.6.4 · spring-projects/spring-security (github.com)

RegexRequestMatcher 클래스의 변경 사항을 확인했습니다. 5.6.4 버전에서는 이 클래스가 5.6.3 버전처럼 기본 .을 사용하는 대신 Pattern.DOTALL을 사용하는 것을 볼 수 있습니다.
여기서:
Pattern: java.util.regex 패키지에 있는 3개 클래스 중 하나로, 정규 표현식을 처리하는 기능을 담당합니다.Pattern.DOTALL: 이 플래그를 사용하면 정규 표현식의 “.”이 \n , \r 같은 줄바꿈 문자를 포함한 모든 문자와 매치됩니다.Pattern.CASE_INSENSITIVE: 대문자와 소문자를 구분하지 않습니다.
기본적으로 정규 표현식의 .은 \n, \r 같은 줄바꿈 문자를 제외한 모든 문자와 매치됩니다. 따라서 어떤 문자열의 패턴을 검증하는 regex 함수가 있을 때, 문자열에 줄바꿈 문자가 포함되어 있으면 해당 regex 함수는 매치되지 않습니다. 이를 방지하려면 Pattern.DOTALL 플래그를 사용할 수 있습니다.
그러나 누군가 의도적으로 \n 대신 %0d를, \r 대신 %0a를 사용하면 위 regex는 여전히 매치되지 않습니다. 그래서 5.6.4 버전에서는 RegexRequestMatcherTests.java에 이 경우를 추가로 확인하는 코드가 추가되었습니다. 구체적으로 %0d와 %0a를 각각 \n과 \r로 변환한 다음 regex로 검사합니다.

1단계: Spring Initializr를 사용하여 Spring Security와 Spring Web 2개의 dependency를 포함한 Spring Boot 웹 애플리케이션을 생성합니다.

2단계: /admin/* 경로로 요청이 오면 This is a CVE-2022-22978 demo 문구를 출력하는 Controller를 생성합니다.

3단계: 사용자가 /admin/<anything> 경로에 접근할 때마다 regexMatchers("/admin/.*").authenticated()를 사용하여 인증 메커니즘을 설정합니다. 이것이 바로 공격자가 인증 없이 /admin/<anything> 페이지의 콘텐츠를 볼 수 있도록 악용하는 취약점입니다.

4단계: 구성 파일에서 취약점이 포함된 Spring Security 버전을 선언합니다. 여기서는 5.6.3 버전을 선택했습니다.

5단계: gradlew bootRun 명령으로 애플리케이션을 실행합니다. 프로그램은 기본적으로 Apache Tomcat을 사용하여 8080 포트에서 수신 대기합니다. /admin/xyz 경로에 접속합니다(/admin/으로 시작하는 경로는 무엇이든 상관없습니다).

결과로 403 Forbidden 코드가 반환되는데, 이는 아직 인증되지 않아 접근할 수 없음을 의미합니다.
이때 Spring Security(버전 5.6.3)의 regexMatchers 함수가 \r(%0d), \n(%0a) 같은 줄바꿈 문자를 매치하지 않는 취약점을 이용하면, payload /admin/%0dxyz로 인증 없이 위 경로에 접근할 수 있습니다.

마찬가지로 /admin/%0axyz payload도 사용할 수 있습니다.

이처럼 매우 간단한 payload 하나만으로 CVE-2022-22978 취약점을 성공적으로 악용했습니다.
5.7.1 사용
위와 동일한 payload /admin/%0dxyz로 웹 공격을 시도합니다.

이때 앱은 공격자가 원하는 응답을 반환하지 않습니다.
git clone https://github.com/ducluongtran9121/CVE-2022-22978-PoC.git
cd CVE-2022-22978-PoC
gradlew bootRun
Java 18
Gradle 7.4.1