Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
rewrite-cve-2026-22732 — OpenRewrite 레시피로, Content-Length 헤더 오용을 식별하고 즉시 헤더 작성 구성을 생성하여 Spring Security 헤더 억제(CVE-2026-22732)를 탐지하고 수정합니다. | Kitploit
도구/GitHubGitHub/moderneinc/rewrite-cve-2026-22732
Static AnalysisVulnerability AnalysisCode AnalysisWeb SecurityDevSecOps
GitHubmoderneinc/rewrite-cve-2026-22732

rewrite-cve-2026-22732

OpenRewrite 레시피로, Content-Length 헤더 오용을 식별하고 즉시 헤더 작성 구성을 생성하여 Spring Security 헤더 억제(CVE-2026-22732)를 탐지하고 수정합니다.

저장소 보기

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
3611일 전아직 검토되지 않음
공유

rewrite-cve-2026-22732

CVE-2026-22732에 취약한 코드를 탐지하는 OpenRewrite 레시피입니다. 이는 세 가지 응답 메서드 중 하나를 통해 Content-Length를 설정하면 Spring Security의 OnCommittedResponseWrapper를 우회하는 Spring Security 결함입니다. 래퍼가 헤더를 인식하지 못하므로 onResponseCommitted()가 실행되지 않고, 지연 추가되는 보안 헤더(X-Frame-Options, X-Content-Type-Options, Cache-Control 등)가 조용히 누락됩니다.

탐지 대상

취약한 Spring Security 6.4.12 + Spring Boot 3.4.3 / 내장 Tomcat에서 확인된 실제 트리거는 다음과 같습니다:

  1. 래퍼를 우회하는 오버로드를 통한 서블릿 Content-Length

    response.setHeader("Content-Length", "42");
    response.setIntHeader("Content-Length", 42);
    response.addIntHeader("Content-Length", 42);
    

    이 세 가지 오버로드는 OnCommittedResponseWrapper에서 재정의되지 않습니다. 이후 본문 쓰기가 선언된 길이를 완성하고 컨테이너는 지연 헤더 작성기를 실행하지 않고 커밋합니다.

  2. HttpHeaders를 통한 WebFlux Content-Length

    serverHttpResponse.getHeaders().set("Content-Length", "42");
    serverHttpResponse.getHeaders().add("Content-Length", "42");
    serverHttpResponse.getHeaders().setContentLength(42L);
    
  3. WebFlux 무조건적 응답 커밋

    serverHttpResponse.writeWith(Mono.just(dataBuffer));
    serverHttpResponse.writeAndFlushWith(publisher);
    serverHttpResponse.setComplete();
    

이 레시피는 Spring Security 존재 여부(즉, org.springframework.security.* 타입을 참조하지 않는 파일에서는 아무것도 출력하지 않음)와 영향받는 Spring Security 버전 범위에 따라 게이팅됩니다. 2026-03-19에 게시된 Spring 권고에 따르면 영향 범위와 수정 버전은 다음과 같습니다:

시리즈영향 범위수정 버전
5.7.x5.7.0 – 5.7.215.7.22 (엔터프라이즈)
5.8.x5.8.0 – 5.8.235.8.24 (엔터프라이즈)
6.3.x6.3.0 – 6.3.146.3.15 (엔터프라이즈)
6.4.x6.4.0 – 6.4.146.4.15 (엔터프라이즈)
6.5.x6.5.0 – 6.5.86.5.9 (OSS)
7.0.x7.0.0 – 7.0.37.0.4 (OSS)

해당 시리즈의 수정 버전 이상(또는 7.0 / 6.5 이후의 향후 시리즈)의 Spring Security 버전을 해석하는 프로젝트는 영향받지 않는 것으로 처리되며 싱크 또는 파일별 마커를 받지 않습니다. 버전을 해석할 수 없는 프로젝트는 일반적인 패턴 기반 탐지로 폴백되어 스캐너가 반증할 수 없는 발견을 보고하는 쪽으로 오류를 범합니다. SpringSecurityVersionByProject 데이터 테이블은 여전히 해석된 버전을 기록하고 각 프로젝트를 영향 여부로 플래그하므로 필터링된 내용을 감사할 수 있습니다.

의도적으로 플래그하지 않는 항목

다음은 위험해 보이지만 래퍼가 추적하므로 응답이 커밋되기 전에 보안 헤더가 작성됩니다:

코드안전한 이유
response.setContentLength(int) / setContentLengthLong(long)재정의됨 — 래퍼가 선언된 길이를 기록하고 본문이 완료되면 onResponseCommitted()를 실행합니다.
response.flushBuffer()재정의됨 — super.flushBuffer() 이전에 doOnResponseCommitted()를 호출합니다.
response.getOutputStream().write(..) / flush() / close()SaveContextServletOutputStream을 반환합니다. 모든 쓰기/플러시/닫기는 위임 전에 doOnResponseCommitted()를 실행합니다.
response.getWriter().write(..) / print(..) / println(..) / flush() / close()SaveContextPrintWriter를 반환합니다. 동일한 패턴입니다.
response.addHeader("Content-Length", v)래퍼에서 특수 처리됨 — setContentLength(long)을 통해 라우팅됩니다.

Semgrep 데모의 /vuln/flush 엔드포인트는 flushBuffer()가 트리거라고 주장하지만, 취약한 Spring Security 6.4.12에서 응답은 실제로 여섯 개의 보안 헤더를 모두 반환합니다. 데모의 실제 트리거는 /vuln/stream 및 /vuln/content-length의 setIntHeader("Content-Length", ...) 호출입니다.

탐지

다음을 실행하세요:

레시피용도
io.moderne.recipe.cve202622732.FindSpringSecurityHeaderSuppression모든 탐지를 실행하고 버전 보고 테이블을 출력합니다

구성 요소 (고급)

위의 집계기는 두 개의 더 작은 레시피로 구성됩니다. 하나의 탐지만 원하는 경우 개별적으로 호출할 수 있습니다.

레시피용도
io.moderne.recipe.cve202622732.FindHttpResponseContentLengthHeadersetHeader / setIntHeader / addIntHeader(서블릿) 또는 HttpHeaders.set / add(WebFlux)에 도달하는 "Content-Length" 리터럴에 대한 오염 흐름
io.moderne.recipe.cve202622732.FindHttpResponseContentLengthOrFlushBufferWebFlux 무조건적 커밋: writeWith, writeAndFlushWith, setComplete, HttpHeaders.setContentLength

수정

다음을 실행하세요:

레시피용도
io.moderne.recipe.cve202622732.FixSpringSecurityHeaderSuppression각 프로젝트가 실제로 취할 수 있는 가장 저렴한 수정을 선택합니다

두 단계를 순서대로 실행합니다.

1. 프로젝트 자체 시리즈의 수정 버전으로 업그레이드. Spring Security는 수정 버전을 Maven Central에 6.5.9 및 7.0.4로 게시했습니다. 각 업그레이드는 FindAffectedSpringSecuritySeries 사전 조건에 게이팅됩니다. UpgradeDependencyVersion은 대상이 더 새로운 버전인지만 확인하기 때문입니다. 7.0.4로 이동하라고 지시하면 5.8 프로젝트를 두 개의 메이저 버전을 가로질러 끌고 갈 수 있습니다.

2. 1단계에서 수정할 수 없는 항목에 대해 선제적 헤더 작성 구성을 추가. 이는 프로젝트당 하나의 @Configuration 클래스를 생성합니다:

@Bean
public static BeanPostProcessor eagerHeaderWriterFilterBeanPostProcessor() {
    return new BeanPostProcessor() {
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (bean instanceof HeaderWriterFilter) {
                ((HeaderWriterFilter) bean).setShouldWriteHeadersEagerly(true);
            }
            return bean;
        }
    };
}

헤더를 미리 작성하면 래퍼가 커밋을 관찰하는지 여부가 무의미해지므로 프로젝트의 모든 싱크가 한 번에 닫힙니다. 여기에는 "알려진 제한 사항"의 Map 흐름처럼 오염 분석이 도달할 수 없는 싱크도 포함됩니다. BeanPostProcessor는 AutowireBeanFactoryObjectPostProcessor가 빈 팩토리를 통해 필터를 초기화하므로 HttpSecurity DSL로 빌드된 필터를 볼 수 있습니다. 이 CVE에 대해 독립적으로 게시된 두 가지 수정 사항이 정확히 이 형태를 사용합니다(hmcts/idam-web-public 및 armory-io의 Spinnaker 포크는 동등한 ObjectPostProcessor를 통해).

2단계는 1단계가 도울 수 없는 프로젝트를 다룹니다:

상황업그레이드가 작동하지 않는 이유
5.7, 5.8, 6.3, 6.4수정 사항이 Spring Enterprise 구독자에게만 제공됨 — Maven Central에 없음
6.0 - 6.2해당 시리즈에는 수정 버전이 게시된 적 없음
가져온 BOM으로 관리되는 버전업그레이드가 편집할 로컬 선언이 없음

마지막 행은 가장자리 사례가 아닙니다. nla/bamboo는 오픈소스 수정 버전이 있는 시리즈인 7.0.3을 전적으로 Spring Boot BOM에서 해석하므로 버전 확인만으로는 두 단계 모두에서 건너뛰고 취약한 상태로 남게 됩니다. 따라서 AddEagerHeaderWriterConfiguration은 프로젝트에 오픈소스 수정 버전이 있고 자체 버전을 선언한 경우에만 업그레이드에 위임합니다.

생성된 클래스는 @EnableWebSecurity 클래스가 있는 경우 그 옆에 배치되고, 없으면 @SpringBootApplication, 그 다음에는 모든 @Configuration으로 폴백되므로 항상 컴포넌트 스캔이 도달하는 위치에 배치됩니다. 이미 헤더를 선제적으로 작성하는 프로젝트나 패치된 OnCommittedResponseWrapper를 벤더링하는 프로젝트(jogetworkflow/jw-community처럼)는 그대로 둡니다.

구성 요소 (고급)

레시피용도
io.moderne.recipe.cve202622732.UpgradeSpringSecurityToPatchedVersion시리즈 게이팅된 6.5.9 / 7.0.4 업그레이드
io.moderne.recipe.cve202622732.AddEagerHeaderWriterConfiguration생성된 구성 자체
io.moderne.recipe.cve202622732.FindAffectedSpringSecuritySeries영향받는 시리즈의 프로젝트를 표시합니다. 업그레이드 사전 조건입니다

실행 중인 서버로 검증

취약한 Spring Security 6.4.12의 semgrep/cve-2026-22732-demo에 내장 Tomcat을 대상으로 적용했습니다. 해당 HeaderVerificationTest는 보안 헤더가 누락되었음을 주장하므로 작동하는 수정 사항은 이를 실패하게 만듭니다:

엔드포인트수정 전수정 후
/vuln/streamX-Content-Type-Options: nullnosniff
/vuln/content-lengthX-Content-Type-Options: nullnosniff
/safenosniffnosniff

X-Frame-Options 및 Cache-Control도 동일한 패턴을 따릅니다.

빌드되는 코퍼스의 16개 저장소(식별된 29개 중)에서 수정 사항은 세 개에 대한 구성을 생성하고 나머지는 올바르게 그대로 두었습니다:

저장소결과
semgrep/cve-2026-22732-demo@EnableWebSecurity 옆의 com/example/vuln에 생성됨. 컴파일되고 헤더가 복원됨
nla/bamboo@SpringBootApplication 옆의 ui/src/bamboo에 생성됨. 컴파일됨. 업그레이드가 도달할 수 없는 BOM 관리 7.0.3 사례
star-whale/starwhale@EnableWebSecurity 옆의 ai/starwhale/mlops/configuration/security에 생성됨. 컴파일됨(선언된 대상인 JDK 11)
hmcts/idam-web-public그대로 둠 — 이미 setShouldWriteHeadersEagerly 호출
okta/okta-idx-java (6.5.9), psi-probe (6.5.11), Ant-Media-Server (6.5.11)그대로 둠 — 해당 시리즈의 수정 버전 이후
apache/shenyu (6.3.1)그대로 둠 — 리액티브 전용. HeaderWriterFilter 뒤에 서블릿 API가 없고 CVE는 서블릿 전용
brutusin/Brutusin-RPC (4.0.4)그대로 둠 — setShouldWriteHeadersEagerly(5.2) 이전
bootplus, template-app, front50, igor, rosco, spring-security, reportserver그대로 둠 — 영향받는 Spring Security 버전이 해석되지 않음

세 개의 패치된 저장소에 수정 사항을 다시 실행하면 추가 생성이 없으므로 수정은 실제 프로젝트에서 자체 출력에 대해 멱등적입니다.

도구 다운로드