Skip to Content
프로젝트Woori-CodeShare운영보안 취약점 대응2025년 11월 12일

2025년 11월 12일 보안 취약점 대응

문제 발견 배경

2025년 11월 12일 SSAFY에서 보안 취약점에 대해 듣게 되었고, 프로젝트에 보안 취약점이 있지 않을까 하는 궁금증에 Spring Framework 의존성을 점검해보며 8개의 보안 취약점 발견하게 되었습니다.

build.gradle
plugins { id 'java' id 'org.springframework.boot' version '3.3.7' id 'io.spring.dependency-management' version '1.1.7' } dependencies { implementation("org.springframework.boot:spring-boot-starter-websocket") implementation("org.webjars:webjars-locator-core") implementation("org.webjars:sockjs-client:1.0.2") implementation("org.webjars:stomp-websocket:2.3.3") implementation("org.webjars:bootstrap:3.3.7") implementation("org.webjars:jquery:3.1.1-1") implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0' implementation 'org.springframework.security:spring-security-crypto' runtimeOnly 'com.mysql:mysql-connector-j' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'io.micrometer:micrometer-registry-prometheus' implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" }

발견된 의존성별 취약점 목록

Spring Boot 

  • CVE-2025-22235 : Spring Boot Actuator EndpointRequest 잘못된 매처 생성 취약점 (High, CVSS 7.3)
  • CVE-2025-41249 : Spring Framework 애노테이션 탐지 취약점 (High, CVSS 7.5)
  • CVE-2025-22233 : Spring Framework DataBinder 대소문자 구분 우회 취약점 (Low, CVSS 3.1)

Spring Boot Starter WebSocket 

Spring Boot Starter Web 

Spring Boot Starter Test 

  • CVE-2025-41249 : Spring Framework 애노테이션 탐지 취약점 (High, CVSS 7.5)
  • CVE-2024-57699 : Json-smart 제어되지 않은 재귀 DoS 취약점 (High, CVSS 7.5)
  • CVE-2024-31573 : XMLUnit 안전하지 않은 XSLT 기본 설정 취약점 (Medium, CVSS 4.0)

취약점 심각도 요약

심각도개수CVE 목록
High3개CVE-2025-41249, CVE-2025-22235, CVE-2024-57699
Medium4개CVE-2025-41234, CVE-2025-41242, CVE-2025-41254, CVE-2024-31573
Low1개CVE-2025-22233

임시 대응 조치

발견된 8개의 CVE를 해결하려면 Spring Framework 6.2.12 이상이 필요한데, 문제는 현재 프로젝트에서 사용 중인 Spring Boot 3.3.x 버전에서는 이 버전의 Spring Framework를 포함하는 릴리스가 제공되지 않는다는 점이었습니다.

업그레이드 대상으로는 당연히 최신 버전인 3.5.7이 가장 먼저 눈에 들어왔지만, 3.3.7에서 바로 3.5.x로 올리게 되면 두 단계의 메이저 버전을 건너뛰게 되어 예상치 못한 호환성 문제가 발생할 위험이 상당히 컸습니다. 그래서 모든 취약점을 해결하면서도 안정성을 최대한 유지할 수 있는 3.4.11 버전을 최소 안정 버전으로 선택했습니다.

build.gradle
plugins { id 'java' id 'org.springframework.boot' version '3.4.11' id 'io.spring.dependency-management' version '1.1.7' }

세부 대응 조치

CVE-2025-41249 

CVE-2025-41249 취약점은 Spring Framework의 애노테이션 탐지 메커니즘파라미터화된 슈퍼타입과 무제한 제네릭을 사용하는 타입 계층 구조에서 메서드의 보안 애노테이션을 올바르게 해석하지 못하는 취약점입니다.

이 취약점은 다음과 같은 상황에서 발생합니다:

  1. 파라미터화된 타입 계층 구조 사용

    public interface GenericService<T> { void process(T data); } public class UserService implements GenericService<User> { @PreAuthorize("hasRole('ADMIN')") // 제대로 탐지되지 않을 수 있음 @Override public void process(User data) { // ... } }
  2. 무제한 제네릭을 사용하는 슈퍼타입

    public abstract class BaseController<T extends Serializable> { protected abstract void handleRequest(T request); } public class AdminController extends BaseController<AdminRequest> { @Secured("ROLE_ADMIN") // 무시될 수 있음 @Override protected void handleRequest(AdminRequest request) { // ... } }

프로젝트에서 @EnableMethodSecurity@PreAuthorize, @Secured 같은 애노테이션 기반의 보안 메커니즘을 사용하고 있지 않았기 때문에, 다행히도 이 취약점의 영향을 받지 않았습니다

CVE-2025-22235 

CVE-2025-22235 취약점은 Spring Boot Actuator의 EndpointRequest.to() 메서드가 비활성화되거나 웹에 노출되지 않은 엔드포인트를 참조할 때, 의도한 엔드포인트 경로 대신 /null/** 패턴의 잘못된 매처를 생성하는 취약점입니다.

이 취약점은 다음 4가지 조건이 모두 충족될 때만 발생합니다:

  1. Spring Security를 사용하고 있어야 함
  2. Spring Security 설정에서 EndpointRequest.to()를 사용해야 함
  3. EndpointRequest.to()가 참조하는 엔드포인트가 비활성화되어 있거나 웹에 노출되지 않아야
  4. 애플리케이션이 /null 경로 요청을 처리하며, 이 경로에 대한 보호가 필요해야 함

모든 조건이 충족된 취약한 코드 예시:

SecurityConfig.java
@Configuration @EnableWebSecurity // 조건 1: Spring Security 사용 public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests(auth -> auth .requestMatchers(EndpointRequest.to("health")).permitAll() // 조건 2: EndpointRequest.to() 사용 .anyRequest().authenticated() ); return http.build(); } }
application.properties
# 조건 3: health 엔드포인트가 웹에 노출되지 않음 management.endpoints.web.exposure.include=info,metrics # 또는 management.endpoint.health.enabled=false # health 엔드포인트 비활성화
NullController.java
@RestController public class NullController { // 조건 4: /null 경로를 처리하며, 이 경로가 보호되어야 함 @GetMapping("/null/admin") public String adminPanel() { return "관리자 전용 페이지"; // 인증 없이 접근 가능해짐! } }

이 경우 PathMappedEndpoints.getPath("health")null을 반환하고, 이 null 값이 필터링되지 않은 채로 매처 생성에 사용되어 /null/** 경로에 대한 permitAll() 규칙이 만들어집니다. 결과적으로 인증이 필요한 /null/admin 경로에 인증 없이 접근할 수 있게 됩니다.

프로젝트에서는 Spring Security를 사용하고 있지만, EndpointRequest.to()를 사용하지 않았기 때문에 이 취약점의 영향을 받지 않았습니다.

CVE-2024-57699 

CVE-2024-57699 취약점은 json-smart 라이브러리의 JSON 파싱 과정에서 중첩된 { 토큰에 대한 재귀 깊이 제한이 없어 발생하는 스택 소진 DoS 취약점입니다. 이는 CVE-2023-1370의 불완전한 수정으로 인해 발생했습니다.

이 취약점은 다음과 같은 상황에서 발생합니다:

  1. 악의적으로 제작된 JSON 페이로드

    malicious.json
    {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{
  2. json-smart를 사용한 JSON 파싱

    JsonParserExample.java
    import net.minidev.json.JSONValue; public class JsonParserExample { public void parseExternalJson(String jsonInput) { // json-smart 2.5.0~2.5.1 사용 시 중첩된 '{' 토큰으로 StackOverflowError 발생 Object result = JSONValue.parse(jsonInput); } }

이 경우 공격자가 대량의 중첩된 { 토큰을 포함한 JSON을 전송하면, json-smart 라이브러리가 재귀적으로 파싱을 시도하다가 스택 메모리가 고갈되어 StackOverflowError가 발생합니다. 결과적으로 애플리케이션이 크래시되어 서비스 거부 상태가 됩니다.

프로젝트에서는 json-smart가 테스트 의존성(spring-boot-starter-test)에만 포함되어 있고, 프로덕션 코드에서 외부 JSON 입력을 직접 파싱하지 않으며, CI/CD 파이프라인이나 개발 환경에서도 외부 JSON을 처리하지 않기 때문에 이 취약점의 영향을 받지 않았습니다.

CVE-2025-41234 

CVE-2025-41234 취약점은 Spring Framework에서 Content-Disposition 헤더에 non-ASCII charset을 사용하고 filename을 사용자 입력에서 가져올 때 발생하는 Reflected File Download 공격 취약점입니다.

이 취약점은 다음과 같은 상황에서 발생합니다:

  1. 사용자 입력을 파일명으로 사용하는 파일 다운로드

    FileDownloadController.java
    @RestController public class FileDownloadController { @GetMapping("/download") public ResponseEntity<byte[]> downloadFile(@RequestParam String filename) { byte[] fileContent = getFileContent(); // 취약한 코드: 사용자 입력을 그대로 파일명으로 사용 ContentDisposition contentDisposition = ContentDisposition.builder("attachment") .filename(filename, StandardCharsets.UTF_8) // non-ASCII charset + 사용자 입력 .build(); HttpHeaders headers = new HttpHeaders(); headers.setContentDisposition(contentDisposition); return ResponseEntity.ok() .headers(headers) .body(fileContent); } }
  2. 악의적으로 인코딩된 파일명 요청

    GET /download?filename=report%22%3B%20evil.cmd HTTP/1.1 Host: example.com

이 경우 공격자가 악의적으로 조작된 파일명을 전송하면, 응답 헤더에 실행 가능한 확장자(.cmd, .bat)를 가진 파일명이 포함됩니다. 사용자가 이 파일을 다운로드하고 실행하면 악성 명령어가 실행될 수 있습니다.

프로젝트에서는 파일 다운로드 기능을 제공하지 않으며, Content-Disposition 헤더를 사용하는 API가 없기 때문에 이 취약점의 영향을 받지 않았습니다.

CVE-2025-41242 

CVE-2025-41242 취약점은 Spring Framework MVC 애플리케이션이 비준수 Servlet 컨테이너에 배포될 때 발생하는 경로 탐색 취약점입니다.

이 취약점은 다음 3가지 조건이 모두 충족될 때만 발생합니다:

  1. WAR 파일로 배포되거나 임베디드 Servlet 컨테이너를 사용해야 함
  2. Servlet 컨테이너가 의심스러운 URI 시퀀스를 거부하지 않아야
  3. 애플리케이션이 Spring의 정적 리소스 처리 기능을 사용해야 함

모든 조건이 충족된 취약한 환경:

WebMvcConfig.java
@Configuration @EnableWebMvc public class WebMvcConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // 조건 3: Spring 정적 리소스 처리 활성화 registry.addResourceHandler("/static/**") .addResourceLocations("classpath:/static/"); } }
GET /static/..%2F..%2F..%2Fetc%2Fpasswd HTTP/1.1 Host: example.com

이 경우 공격자가 URI 인코딩된 경로 탐색 시퀀스(..%2F)를 사용하여 요청을 보내면, 비준수 Servlet 컨테이너에서는 이를 거부하지 않고 Spring으로 전달하게 되고, Spring이 이를 부적절하게 처리하면 의도하지 않은 디렉토리의 파일에 접근할 수 있습니다.

프로젝트에서는 Spring Boot의 기본 임베디드 Tomcat을 사용하고 있는데, Apache Tomcat과 Eclipse Jetty는 기본 보안 설정에서 의심스러운 URI 시퀀스를 자동으로 거부하기 때문에 이 취약점의 영향을 받지 않았습니다.

CVE-2025-41254 

CVE-2024-31573 

CVE-2024-31573 취약점은 XMLUnit for Java 2.10.0 미만 버전에서 XSLT 확장 함수가 기본적으로 활성화되어 있어, 신뢰되지 않은 스타일시트를 처리할 때 임의 코드 실행이 가능한 취약점입니다.

이 취약점은 다음과 같은 상황에서 발생합니다:

  1. XMLUnit을 사용한 XSLT 변환

    XmlTransformTest.java
    import org.xmlunit.transform.Transformation; public class XmlTransformTest { @Test public void testXsltTransformation() { // 취약한 코드: 외부 XSLT 스타일시트를 검증 없이 사용 String xslt = loadExternalStylesheet(); // 외부에서 로드한 XSLT Transformation transformation = new Transformation() .setStylesheet(xslt) .setSource(xmlInput); String result = transformation.transformToString(); } }
  2. 악의적인 XSLT 스타일시트

    malicious.xslt
    <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:java="http://xml.apache.org/xalan/java"> <xsl:template match="/"> <!-- XSLT 확장 함수로 임의 Java 코드 실행 --> <xsl:value-of select="java:lang.Runtime.getRuntime().exec('malicious-command')"/> </xsl:template> </xsl:stylesheet>

이 경우 공격자가 악의적인 XSLT 스타일시트를 제공하면, XMLUnit이 XSLT 변환을 수행할 때 XSLT 확장 함수를 통해 Java 메서드를 호출할 수 있습니다. 이를 통해 서버에서 임의의 코드가 실행되어 시스템이 완전히 장악될 수 있습니다.

프로젝트에서는 XMLUnit이 테스트 의존성(spring-boot-starter-test)에만 포함되어 있고, 테스트 코드에서 외부 XSLT 스타일시트를 로드하거나 처리하지 않기 때문에 이 취약점의 영향을 받지 않았습니다.

CVE-2025-22233 

Last updated on