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

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

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

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-94545-nextjs-og-poc — CVE-2026-94545(Next.js next/og ImageResponse SVG 인젝션)를 재현하는 격리된 Docker 랩 및 비파괴 Python 스캐너로, 취약 버전과 패치 버전 대조 및 픽셀 수준 PNG 증거를 제공합니다. | Kitploit
도구/GitHubGitHub/hassham1/cve-2026-94545-nextjs-og-poc
Vulnerability ScannersVulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityLabs & Practice
GitHubhassham1/cve-2026-94545-nextjs-og-poc

CVE-2026-94545-nextjs-og-poc

CVE-2026-94545(Next.js next/og ImageResponse SVG 인젝션)를 재현하는 격리된 Docker 랩 및 비파괴 Python 스캐너로, 취약 버전과 패치 버전 대조 및 픽셀 수준 PNG 증거를 제공합니다.

저장소 보기
1일 전아직 검토되지 않음

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-94545 - Next.js next/og ImageResponse SVG 인젝션 (GHSA-vcvr-r3jv-pc5j)

CVE-2026-94545, 즉 Next.js ImageResponse SVG 직렬화 인젝션(업스트림: Satori GHSA-wx4j-mvgx-mqwp)을 격리된 루프백 전용 랩에서 재현하고 검증하기 위한 보안 연구 자료입니다.

  • 영향 받는 버전: Next.js >=16.2.0 <16.3.6 (Node.js ImageResponse만 해당)
  • 수정 버전: 16.3.6 (Satori 하드닝, 커밋 26a52aff); 15.5.26은 관련 하드닝을 포함하며, 15.x는 RCE 이슈의 영향을 받지 않음
  • 심각도: 치명적 (권고문); Satori의 부적절한 이스케이프 -> 공격자가 임베드된 SVG 문서를 제어; 권고문에 따른 RCE는 다운스트림 SVG 파서에 의존
  • 업스트림: vercel/satori GHSA-wx4j-mvgx-mqwp

본인이 소유하거나 명시적으로 테스트 권한을 받은 시스템에서만 사용하십시오. 스캐너는 비파괴적입니다: 이미지를 렌더링하고 픽셀을 카운트할 뿐입니다. 대상에 아무것도 쓰거나 저장하거나 실행하지 않습니다.

판정

상태: 제공된 랩에서 입증됨.

권고문의 정확한 라우트 패턴(공격자 값이 <svg><title>{value}</title></svg>로 들어감)에 대해:

root@kitploit:~
next 16.3.5 (취약): 주입된 500x150 빨간 rect가 PNG에 렌더링됨
                    (응답에서 75,000개의 #FF0000 픽셀 측정)
next 16.3.6 (패치됨): 값이 이스케이프됨, 빨간 픽셀 0개
satori 0.25.0 (취약): 직렬화된 SVG 문자열에 페이로드가 원시 상태로 존재
satori 0.33.5 (수정됨): 페이로드가 &lt;/title&gt;로 이스케이프됨

이는 인젝션 프리미티브를 엔드투엔드(직렬화기 -> 임베드된 SVG -> 래스터화된 출력)로 입증합니다. 원격 코드 실행을 입증하지는 않습니다: 권고문은 RCE를 다운스트림 SVG 파서에 연결하며, 그 취약점 세부 사항은 작성 시점에 공개되지 않았습니다. 파일 읽기, SSRF, 코드 실행은 주장하지 않습니다.

근본 원인 (수정 커밋에 대해 검증됨)

Satori는 <svg> 노드를 translateSVGNodeToSVGString()(src/handler/preprocess.ts)으로 직렬화하는데, 이 함수는 이스케이프 없이 출력 XML에 보간했습니다:

  1. 텍스트 노드가 String(node)를 통해 반환됨 - 이스케이프되지 않음 (현재는 escapeXMLText).
  2. 속성 값이 따옴표 안에 원시 상태로 보간됨 - "가 빠져나감.
  3. 속성 이름이 원시 상태로 보간됨 - 공백/따옴표가 새 속성을 주입함.
  4. style 값이 원시 상태로 보간됨.
  5. 임베드된 SVG 데이터 URL 인코더가 &를 인코딩하지 않아, 내부 XML 엔티티가 외부 SVG 파싱을 통과해 살아남음.
  6. expand.ts가 내부 스타일 속성(접두사 _)을 직렬화된 스타일에 전달함 - 현재는 거부됨.

수정(satori@26a52aff)은 모든 것을 하드닝된 buildXMLString()을 통해 라우팅하여 값을 이스케이프하고 XML 이름을 검증합니다. 이 랩은 이를 모두 동작적으로 검증합니다; 정확한 요청과 픽셀 증거는 poc/에 있습니다.

빠른 시작

요구 사항: Docker(Compose v2 포함), 호스트의 Python 3.10+ (스캐너용), 첫 실행 시 npm에 대한 네트워크 접근.

root@kitploit:~
./lab verify

취약한 앱([email protected]의 벤더링된 next/og)을 빌드하고, 마커 rect가 HTTP 응답에 렌더링되어야 함을 요구한 다음, 패치된 앱([email protected])을 빌드하고 그 부재를 요구합니다.

예상 증거

취약한 컨트롤:

root@kitploit:~
[*] #FF0000 pixels: 75000 (threshold 10000)
[!!!] INJECTION CONFIRMED: the attacker value escaped <title> and
      became a rendered SVG element in the generated image.
RESULT: VULNERABLE CONTROL CONFIRMED

패치된 컨트롤:

root@kitploit:~
[*] #FF0000 pixels: 0 (threshold 10000)
[=] no injection observed
RESULT: PATCHED CONTROL CONFIRMED

수동 랩 라이프사이클

root@kitploit:~
./lab start vulnerable   # 16.3.5 app on http://127.0.0.1:9481/og
./lab test               # assert injection renders
./lab start patched      # 16.3.6 app
./lab test               # assert absence
./lab status
./lab reset

스캐너를 직접 실행 (기본 루프백; 권한을 받은 외부 대상은 명시적 오버라이드 필요):

root@kitploit:~
python3 poc/scan.py http://127.0.0.1:9481/og
python3 poc/scan.py https://host.example/og --param value \
  --allow-authorized-non-loopback [--insecure]

탐지 작동 방식 (그리고 안전한 이유)

페이로드는 500x150 순수 빨간색 <rect>를 담은 균형 잡힌 XML입니다. 취약한 엔드포인트에서는 값이 <title>을 빠져나가고 rect가 임베드된 SVG 문서의 실제 요소가 됩니다; 스캐너는 반환된 PNG에서 정확한 #FF0000 픽셀을 카운트합니다(예상 75,000개; 임계값 10,000). 패치된 엔드포인트에서는 값이 이스케이프된 텍스트이고 빨간색이 렌더링되지 않습니다. 프로브는 대상에 아무것도 변경하지 않습니다: GET 요청 하나, 이미지 렌더링 하나.

캐리어는 의도적으로 텍스트가 아닌 <rect>입니다: 임베드된 SVG 내부의 텍스트는 렌더러에 로드 가능한 폰트가 없어 주입되더라도 보이지 않기 때문입니다.

nuclei 템플릿이 없는 이유

이 취약점의 증명은 렌더링된 래스터의 픽셀 내용이며, nuclei 매처는 PNG를 디코딩할 수 없습니다. 크기 차이 템플릿을 만들어 보았으나 거부했습니다: 패치된 앱에서도 이스케이프된 페이로드가 (리터럴 비활성 텍스트로) 여전히 렌더링되므로, 정상 대 페이로드 크기가 패치된 시스템에서도 달라지며, 취약한 델타와 패치된 델타 사이의 구분은 앱별 압축 노이즈입니다. 패치된 시스템에서 발동하는 매처를 배포하는 것은 아무것도 배포하지 않는 것보다 나쁩니다. poc/scan.py를 사용하십시오; 이는 응답 이미지를 정확하게 평가합니다.

영향 받는 버전 및 테스트된 버전

버전평가
Next.js 16.3.5 (벤더링된 @vercel/og)HTTP를 통한 엔드투엔드 인젝션 재현됨
Next.js 16.3.6 (벤더링된 @vercel/og)패치된 네거티브 컨트롤 재현됨
satori 0.25.0 (npm)직렬화된 SVG에 원시 인젝션 (소스 수준)
satori 0.33.5 (npm, 2026년 9월 22일)이스케이프됨 (소스 수준)
Next.js 16.2.0-16.3.4권고문에 따라 영향 받음; 개별 테스트되지 않음
Next.js 15.x벤더 블로그에 따라 RCE 이슈의 영향을 받지 않음

저장소 구조

root@kitploit:~
.
├── .gitignore
├── LICENSE
├── README.md
├── SECURITY.md
├── docker-compose.yml
├── lab
├── app/
│   └── server.mjs        # advisory route pattern over loopback HTTP
└── poc/
    └── scan.py           # non-destructive scanner (Python stdlib: urllib + zlib)

커밋되지 않음: assets/ (npm으로 패킹된 next tarball + 추출된 번들), node_modules/, .lab-state.

검증 경계

주장상태
satori < 수정에서의 SVG 직렬화 인젝션입증됨 (소스 + 동작)
next/og 16.3.5를 통한 주입된 마크업의 엔드투엔드 렌더링입증됨
패치된 네거티브 컨트롤 (16.3.6 / satori 0.33.5)입증됨
속성/스타일 캐리어 (동일 근본 원인)수정 diff에서 근본 원인 확인됨; 텍스트 캐리어 입증됨
주입된 리소스 참조를 통한 SSRF / 파일 읽기테스트되지 않음
원격 코드 실행주장하지 않음 (공개되지 않은 다운스트림 파서 세부 사항에 의존)

참고 자료

  • GHSA-vcvr-r3jv-pc5j (Next.js)
  • GHSA-wx4j-mvgx-mqwp (Satori)
  • Next.js 보안 업데이트, 2026년 9월 22일
  • Satori 수정 커밋 26a52aff
  • Netlify 고객 권고문 (CVE-2026-94545)

안전 경계

본인이 소유하거나 명시적으로 테스트 권한을 받은 시스템에서만 이 저장소를 실행하십시오. 랩 드라이버는 vulnerable/patched 이외의 변형을 거부하고, 스캐너는 --allow-authorized-non-loopback이 제공되지 않는 한 비루프백 대상을 거부하며, Compose 포트는 127.0.0.1에 바인딩됩니다.

공개 처리에 대해서는 SECURITY.md를 참조하십시오. 이 저장소에는 프로덕션 대상, 고객 데이터, 액세스 토큰 또는 실제 시스템의 증거가 포함되지 않습니다.

라이선스

MIT - LICENSE 참조.

도구 다운로드