
CVE-2023-34035 취약점을 Spring Security에서 시연하며, 취약한 샘플 애플리케이션과 완화된 샘플 애플리케이션을 통해 올바른 서블릿 매핑 및 요청 매처 구성을 학습합니다.
이 저장소는 애플리케이션이 https://spring.io/security/cve-2023-34035[CVE-2023-34035]에 취약할 수 있는 구성을 보여주는 샘플 모음입니다.
다음 조건이 모두 참일 때 애플리케이션이 취약합니다:
Spring MVC가 클래스패스에 있습니다
DispatcherServlet과 최소 하나 이상의 다른 서블릿이 매핑되어 있으며, 그중 하나가 경로 기반 서블릿 매핑(예: /path/**)을 가지고 있습니다
애플리케이션이 /path/** 형식의 서블릿 매핑을 가진 엔드포인트를 참조하기 위해 requestMatchers(String)을 사용합니다
== 샘플
Spring Boot를 사용하는 샘플과 사용하지 않는 샘플이 있습니다.
실패하는 테스트를 포함하는 샘플은 CVE-2023-34035에 취약합니다. 테스트가 통과하는 샘플은 취약하지 않습니다.
모든 경우에서 각 샘플은 Spring Security의 동일한 완화 오류를 포함하고 있습니다. 단, 이러한 완화는 많은 상황에서 임시적이며, 다음 유지보수 릴리스가 나올 때까지 적용된다는 점에 유의하십시오.
=== servlet:java-configuration:dispatcher-servlet-path
https://github.com/jzheaux/cve-2023-34035-mitigations/tree/main/servlet/java-configuration/dispatcher-servlet-path[이 샘플]은 DispatcherServlet이 기본 / 대신 /mvc/*에 배포된 취약한 애플리케이션을 나타냅니다.
Spring MVC가 클래스패스에 있고, DispatcherServlet과 최소 하나 이상의 다른 서블릿이 매핑되어 있으며(그중 하나가 루트가 아닌 경로 기반 서블릿 매핑을 가짐, 이 경우 DispatcherServlet), 애플리케이션이 해당 엔드포인트를 보호하기 위해 requestMatchers(String)을 사용하므로 취약합니다.
=== servlet:java-configuration:jetty
https://github.com/jzheaux/cve-2023-34035-mitigations/tree/main/servlet/java-configuration/jetty[이 샘플]은 DispatcherServlet이 기본 /에 배포된 안전한 애플리케이션을 나타냅니다.
Spring MVC가 클래스패스에 있고 DispatcherServlet이 사용 중이지만, /에 배포되어 있으며 루트가 아닌 경로 기반 서블릿 매핑이 없으므로 취약하지 않습니다.
=== servlet:java-configuration:other-servlets
https://github.com/jzheaux/cve-2023-34035-mitigations/tree/main/servlet/java-configuration/other-servlets[이 샘플]은 DispatcherServlet과 사용자 정의 서블릿 MyServlet이 함께 배포된 취약한 애플리케이션을 나타냅니다.
Spring MVC가 클래스패스에 있고, DispatcherServlet과 최소 하나 이상의 다른 서블릿이 매핑되어 있으며(그중 하나가 루트가 아닌 경로 기반 서블릿 매핑을 가짐, 이 경우 MyServlet), 애플리케이션이 해당 엔드포인트를 보호하기 위해 requestMatchers(String)을 사용하므로 취약합니다.
=== servlet:java-configuration:tomcat
https://github.com/jzheaux/cve-2023-34035-mitigations/tree/main/servlet/java-configuration/tomcat[이 샘플]은 DispatcherServlet이 기본 /에 배포된 안전한 애플리케이션을 나타냅니다.
Spring MVC가 클래스패스에 있고 DispatcherServlet이 사용 중이지만, /에 배포되어 있으며 루트가 아닌 경로 기반 서블릿 매핑이 없으므로 취약하지 않습니다.
=== servlet:java-configuration:two-dispatcher-servlets
https://github.com/jzheaux/cve-2023-34035-mitigations/tree/main/servlet/java-configuration/two-dispatcher-servlets[이 샘플]은 DispatcherServlet과 사용자 정의 서블릿 MyServlet이 함께 배포된 취약한 애플리케이션을 나타냅니다.
Spring MVC가 클래스패스에 있고, DispatcherServlet과 최소 하나 이상의 다른 서블릿이 매핑되어 있으며(그중 하나가 루트가 아닌 경로 기반 서블릿 매핑을 가짐, 이 경우 두 DispatcherServlet 중 하나), 애플리케이션이 해당 엔드포인트를 보호하기 위해 requestMatchers(String)을 사용하므로 취약합니다.
=== servlet:spring-boot:java:dispatcher-servlet-path
https://github.com/jzheaux/cve-2023-34035-mitigations/tree/main/servlet/spring-boot/java/dispatcher-servlet-path[이 샘플]은 DispatcherServlet이 기본 / 대신 /mvc/*에 배포된 취약한 애플리케이션을 나타냅니다.
Spring MVC가 클래스패스에 있고, DispatcherServlet과 최소 하나 이상의 다른 서블릿이 매핑되어 있으며(그중 하나가 루트가 아닌 경로 기반 서블릿 매핑을 가짐, 이 경우 DispatcherServlet), 애플리케이션이 해당 엔드포인트를 보호하기 위해 requestMatchers(String)을 사용하므로 취약합니다.
=== servlet:spring-boot:java:jetty
https://github.com/jzheaux/cve-2023-34035-mitigations/tree/main/servlet/spring-boot/java/jetty[이 샘플]은 DispatcherServlet이 기본 /에 배포된 안전한 애플리케이션을 나타냅니다.
Spring MVC가 클래스패스에 있고 DispatcherServlet이 사용 중이지만, /에 배포되어 있으며 루트가 아닌 경로 기반 서블릿 매핑이 없으므로 취약하지 않습니다.
=== servlet:spring-boot:java:other-servlets
https://github.com/jzheaux/cve-2023-34035-mitigations/tree/main/servlet/spring-boot/java/other-servlets[이 샘플]은 DispatcherServlet과 사용자 정의 서블릿 MyServlet이 함께 배포된 취약한 애플리케이션을 나타냅니다.
Spring MVC가 클래스패스에 있고, DispatcherServlet과 최소 하나 이상의 다른 서블릿이 매핑되어 있으며(그중 하나가 루트가 아닌 경로 기반 서블릿 매핑을 가짐, 이 경우 MyServlet), 애플리케이션이 해당 엔드포인트를 보호하기 위해 requestMatchers(String)을 사용하므로 취약합니다.
=== servlet:spring-boot:java:tomcat
https://github.com/jzheaux/cve-2023-34035-mitigations/tree/main/servlet/spring-boot/java/tomcat[이 샘플]은 DispatcherServlet이 기본 /에 배포된 안전한 애플리케이션을 나타냅니다.
Spring MVC가 클래스패스에 있고 DispatcherServlet이 사용 중이지만, /에 배포되어 있으며 루트가 아닌 경로 기반 서블릿 매핑이 없으므로 취약하지 않습니다.
=== servlet:spring-boot:java:undertow
https://github.com/jzheaux/cve-2023-34035-mitigations/tree/main/servlet/spring-boot/java/undertow[이 샘플]은 DispatcherServlet이 기본 /에 배포된 안전한 애플리케이션을 나타냅니다.
Spring MVC가 클래스패스에 있고 DispatcherServlet이 사용 중이지만, /에 배포되어 있으며 루트가 아닌 경로 기반 서블릿 매핑이 없으므로 취약하지 않습니다.
== 완화
다음과 같은 오류가 발생하는 경우:
requestMatchers(MvcRequestMatcher);
otherwise, please use requestMatchers(AntPathRequestMatcher).따르면 됩니다.
[NOTE]
Spring Security의 5.8.5, 6.0.5, 6.1.2, 6.2.0-M1 버전에는 일부 오탐(false positive)이 있습니다.
이제 많은 경우 다음은 임시적이며, 5.8.6, 6.0.6, 6.1.3, 6.2.0-M2 릴리스가 나올 때까지 적용됩니다.
오류 메시지에서 암시된 바와 같이, 주요 완화 방법은 완전한 RequestMatcher를 사용하는 것입니다.
이는 서블릿 매핑을 더 명확하게 고려할 수 있도록 하기 위함입니다.
예를 들어, 애플리케이션이 /my-servlet/*에 서블릿을 배포하고 다음과 같이 트래픽을 인증하는 경우:
그러면 애플리케이션은 대신 다음과 같이 해야 합니다:
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
@Bean MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) { return new MvcRequestMatcher.Builder(introspector); }
또는 DispatcherServlet이 /spring-mvc/*와 같은 다른 경로에 배포된 경우, 다음 대신:
애플리케이션은 다음과 같이 해야 합니다:
@Bean MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) { return new MvcRequestMatcher.Builder(introspector).servletPath("/spring-mvc"); }
MvcRequestMatcher를 구성할 때 서블릿 경로를 분리하는 것은 요청이 올바르게 일치되도록 하는 데 중요합니다.
== 브랜치
이 저장소에는 Spring Security의 각 마이너 릴리스에 대한 브랜치가 있습니다. 해당 브랜치에는 필요한 완화 조치가 포함된 각 영향받는 샘플에 대한 커밋이 있습니다.
예를 들어, 5.8.x 브랜치에는 완화가 필요한 8개의 샘플을 수정하기 위한 8개의 커밋이 있습니다.
5.8.6, 6.0.6, 6.1.3, 6.2.0-M2가 출시되면 해당 브랜치에 추가 변경 사항이 적용되어 모범 사례 완화 방법이 명확해집니다.