
Spring 프레임워크에 영향을 미치는 CVE-2024-22243의 악용 가능한 시나리오 예시(오픈 리다이렉트 및 SSRF).
작성자: Sean Pesce
이 프로젝트에는 CVE-2024-22243의 악용 가능한 시나리오를 보여주는 예제 웹 애플리케이션이 포함되어 있습니다. CVE-2024-22243은 Java Spring Framework의 URL 파싱 취약점입니다(공식 공개는 여기에서 확인할 수 있습니다).
영향을 받는 Spring 버전은 URL의 "userinfo" 세그먼트를 고유한 방식으로 파싱하여, 다른 많은 일반적인 라이브러리들과 다른 호스트 이름 세그먼트가 추출될 수 있습니다.
이 비정상적인 동작은 UriComponentsBuilder 클래스의 다음 정규 표현식("regex")으로 인해 발생합니다(2014년 이 커밋에서 도입됨):
private static final String USERINFO_PATTERN = "([^@\\[/?#]*)";
이 정규 표현식은 userinfo 세그먼트에서 "왼쪽 대괄호" 문자([)를 허용하지 않습니다. 그러나 Spring은 이러한 동작에서 이례적인 사례로 보입니다. 따라서 UriComponentsBuilder.fromUriString 또는 UriComponentsBuilder.fromHttpUrl로 생성된 UriComponents 객체에 대해 getHost()를 호출하면 예기치 않은 동작이 발생할 수 있습니다. RestTemplate, RestClient 및 WebClient 클래스도 내부적으로 UriComponentsBuilder를 사용하기 때문에 영향을 받습니다. 따라서 구현체는 UriComponentsBuilder를 직접 사용하지 않더라도 취약해질 수 있습니다.
특수하게 제작된 입력의 경우 Spring은 다음 모든 항목과 다른 호스트 이름 값을 반환합니다:
java.net.URI(특정 Java 버전에서만 해당한다고 알려져 있으며, 다른 버전에서는 URISyntaxException이 발생함)java.net.URLcurlandroid.net.Uriokhttp3.HttpUrlurllib.parse.urlparse(이 목록은 완전하지 않습니다.)
이 동작은 종속 구현에서 신뢰하는 호스트 이름을 인가 또는 기타 보안 관련 메커니즘에 사용하는 경우, Spring 기반 웹 애플리케이션을 오픈 리다이렉트 및 서버 측 요청 위조(SSRF)에 취약하게 만들 수 있습니다.
예제 웹 애플리케이션에는 취약한 두 개의 엔드포인트가 있습니다.
첫 번째 엔드포인트인 /redirect는 Spring의 비정상적인 URL 파싱으로 인해 오픈 리다이렉트가 발생할 수 있음을 보여줍니다. 다음과 같은 URL을 사용하여 악용할 수 있습니다:
https://127.0.0.1[@evil.com
두 번째 엔드포인트인 /health-check는 Spring과 Java 표준 라이브러리 URL 클래스 간의 URL 파싱 불일치로 인해 서버 측 요청 위조(SSRF)가 발생할 수 있음을 보여줍니다. 다음과 같은 URL을 사용하여 악용할 수 있습니다:
https://evil.com[@127.0.0.1
Maven으로 이 프로젝트를 빌드하려면 다음 명령을 실행하면 됩니다(OpenJDK 17에서 테스트됨):
mvn clean package
그런 다음 다음과 같은 명령으로 웹 앱을 시작합니다:
java -jar seanpesce-cve-2024-22243.jar 9999
웹 앱은 http://127.0.0.1:9999/에서 접근할 수 있습니다.
Docker 이미지를 빌드하려면 다음 명령을 실행합니다:
docker build -t seanpesce-cve-2024-22243:latest .
그런 다음 다음과 같은 명령으로 웹 앱을 시작합니다:
docker run -i -e PORT=9999 -p 9999:9999 seanpesce-cve-2024-22243:latest
웹 앱은 Docker 호스트의 http://127.0.0.1:9999/에서 접근할 수 있습니다.
이 저장소에는 잠재적으로 취약한 코드 경로를 스캔하는 데 도움이 되는 semgrep 규칙도 포함되어 있습니다. spring-cve-2024-22243_loose.yaml은 취약한 API의 모든 사용에 대해 단순(naive) 스캔을 수행하므로, 종종 많은 수의 오탐(false positive)을 반환합니다. spring-cve-2024-22243_strict.yaml은 더 엄격한 로직과 오염 분석(taint analysis)을 사용하려고 시도합니다. 그러나 이 규칙은 철저히 테스트되지 않았으며, 일부 취약한 구현을 놓칠 가능성이 높습니다(특히 교차 파일 분석에 필요한 Semgrep Pro를 사용하지 않는 경우).