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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-34207 — SSRF 필터는 호스트네임 텍스트를 검사했지만, 실제 목적지는 나중에 DNS에 의해 결정되었습니다. 그 차이로 인해 공격자가 제어하는 웹훅 URL이 루프백, 메타데이터 및 사설 네트워크 대상에 도달할 수 있었습니다. | Kitploit
도구/GitHubGitHub/0xmrma/cve-2026-34207
Vulnerability AnalysisExploitationWeb SecurityPenetration TestingPapers & ResearchLearning & Education
GitHub0xmrma/cve-2026-34207

CVE-2026-34207

SSRF 필터는 호스트네임 텍스트를 검사했지만, 실제 목적지는 나중에 DNS에 의해 결정되었습니다. 그 차이로 인해 공격자가 제어하는 웹훅 URL이 루프백, 메타데이터 및 사설 네트워크 대상에 도달할 수 있었습니다.

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

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-34207

SSRF 필터는 호스트명 텍스트를 검사했지만, 실제 목적지는 나중에 DNS에 의해 결정되었습니다. 이 간격으로 인해 공격자가 제어하는 Webhook URL이 루프백, 메타데이터 및 사설 네트워크 대상에 도달할 수 있었습니다.

소개

저는 오픈소스 챗봇 빌더인 Typebot을 검토하면서 간단한 보안 질문을 염두에 두고 이 문제를 발견했습니다.

SSRF 보호가 호스트명 텍스트를 검증하지만 실제 목적지는 나중에 DNS에 의해 결정된다면 어떻게 될까?

이 경우, 그 질문은 실제 버그로 이어졌습니다.

Typebot의 Webhook / HTTP 요청 블록에 대한 SSRF 보호는 다음만 검증했습니다.

  • URL 문자열
  • 호스트명 리터럴 차단
  • 리터럴 IP 형식

요청을 허용하기 전에 DNS 확인을 하지 않았습니다.

즉, ssrf-repro.example 같은 호스트명은 검증 중에는 무해해 보일 수 있지만, 이후에 다음으로 확인될 수 있었습니다.

  • 127.0.0.1
  • 169.254.169.254
  • 또는 RFC1918/사설 네트워크 공간

그리고 백엔드 HTTP 클라이언트가 여전히 해당 요청을 가져갔습니다.

이 문제는 CVE-2026-34207이 되었습니다.

Typebot: GitHub의 Typebot
CVE: CVE-2026-34207
수정 버전: 3.16.0

이는 널리 사용되는 오픈소스 챗봇 플랫폼인 에 영향을 미쳤습니다. 공식 사이트에서 Typebot은 전 세계 이 신뢰하는 것으로 소개됩니다. 또한 사이트는 과 을 광고합니다.

Typebot
650개 이상의 기업
월 200만 건 이상의 채팅
150만 개 이상의 게시된 봇
photo0

공격 체인

공격자가 제어하는 Webhook URL -> 호스트명이 리터럴 전용 SSRF 검증 통과 -> 허용 결정 전 DNS 확인 없음 -> 백엔드 HTTP 클라이언트가 호스트명을 내부 대상으로 확인 -> 서버 측 요청이 루프백/메타데이터/사설 네트워크에 도달 -> 응답 데이터가 실행 로그를 통해 사용 가능


Typebot의 기능

Typebot은 챗봇 빌더입니다.

사용자가 다음을 수행할 수 있는 흐름을 만들 수 있습니다.

  • 질문하기
  • 구조화된 입력 수집
  • 외부 서비스 호출
  • 비즈니스 로직 연결
  • Webhook / HTTP 요청 블록을 통해 아웃바운드 HTTP 요청 트리거

즉, 아웃바운드 요청 실행은 실제 보안 경계입니다.

여기서 중요한 질문은 Typebot이 Webhook 블록을 지원하는지 여부가 아니었습니다.

진짜 질문은 다음과 같았습니다.

SSRF 보호가 서버가 연결할 실제 대상을 검증하는가, 아니면 URL에 나타나는 호스트명 텍스트만 검증하는가?

이 경우, 먼저 텍스트 형식만 검증했습니다.

그것이 실수였습니다.


이 표면이 살펴볼 가치가 있었던 이유

SSRF 방어는 매우 예측 가능한 방식으로 실패합니다.

대부분의 경우 흥미로운 실수는 다음과 같은 것이 아닙니다.

  • "169.254.169.254 차단을 잊었다"
  • 또는 "localhost 차단을 잊었다"

더 강력한 실수는 경계 실수입니다.

  • 표준화 전에 검증 발생
  • 리디렉션 전에 검증 발생
  • DNS 확인 전에 검증 발생
  • 한 표현에 대해 검증이 발생하지만 네트워크 스택이 다른 표현을 사용함

여기서 살펴볼 올바른 위치였습니다.

Typebot에는 이미 리터럴 메타데이터 IP, 루프백, 사설 범위 및 인코딩된 IP 트릭에 대한 SSRF 강화 로직이 있었습니다.

그러면 다음 질문이 명확해졌습니다.

호스트명이 문자 그대로 위험하지는 않지만, 나중에 위험한 대상으로 확인된다면?

정확히 그런 일이 일어났습니다.


근본 원인

근본 문제는 호스트명 텍스트 기반 대상 검증이지 확인된 IP 주소 기반이 아니었던 것입니다.

취약한 구현에서 validateHttpReqUrl()은 다음을 수행했습니다.

  • URL 구문 분석
  • http: 및 https:만 허용
  • metadata.google.internal, metadata.goog, metadata 및 localhost와 같은 리터럴 호스트명 짧은 목록 차단
  • 리터럴 10진수/16진수/8진수 IP 트릭 감지
  • 리터럴 IPv4/IPv6 주소 구문 분석
  • 호스트명 자체가 이미 리터럴 IP인 경우에만 주소 검증

그것이 중요한 부분입니다.

호스트명이 다음과 같은 일반 값인 경우:

ssrf-repro.example

그러면 parseIPAddress(hostname)이 null을 반환하고 검증기가 거기서 멈췄습니다.

승인 전에 DNS 확인이 발생하지 않았습니다.

따라서 취약한 로직은 본질적으로 다음과 같이 축소되었습니다.

root@kitploit:~
const ip = parseIPAddress(hostname);
if (ip) {
  validateIPAddress(ip);
}

즉, 다음을 의미합니다.

  • 리터럴 위험한 IP는 차단됨
  • 인코딩된 위험한 IP는 차단됨
  • 그러나 위험한 IP로 확인되는 호스트명은 차단되지 않음

버그의 나머지 절반은 실행 경로에 있었습니다.

executeHttpRequest()에서 Typebot은 먼저 검증을 실행한 다음 나중에 ky(request.url, ...)를 사용하여 실제 요청을 수행했습니다.

따라서 순서는 다음과 같았습니다.

  • URL 문자열 검증
  • 호스트명 수락
  • 나중에 실제 아웃바운드 요청 중에 호스트명 확인
  • 확인된 내부 대상에 연결

그것이 전체 취약점입니다.


이것이 단순한 불완전한 필터링이 아닌 보안 문제인 이유

중요한 차이점은 신뢰 결정이 내려진 위치입니다.

많은 버그를 잘못 설명하면 작아 보입니다.

이것을 다음과 같이 설명한다면:

"호스트명 필터가 불완전했다"

품질 문제처럼 들립니다.

그것이 실제 문제가 아닙니다.

실제 문제는 다음과 같습니다.

  • 서버가 실제 대상을 알기 전에 보안 결정을 내렸음
  • 네트워크 스택이 나중에 다른 곳에 연결됨
  • 애플리케이션이 해당 요청을 유효한 것으로 처리함

이는 표면적인 필터링 약점이 아닙니다.

이는 신뢰 경계 실패입니다.

그리고 HTTP 실행기가 실행 로그에 응답 데이터를 기록했기 때문에, 가장 강력한 경우에도 문제가 눈에 띄지 않는 것이 아니었습니다.

따라서 이것은 단순히:

  • "예상치 못한 내부 트래픽이 발생했다"

가 아니라:

  • 내부 트래픽이 발생함
  • 그리고 공격자가 종종 정상적인 애플리케이션 동작을 통해 증거와 응답 콘텐츠를 복구할 수 있었음

그것이 실제 SSRF 취약점입니다.


개념 증명

두 가지 다른 것을 증명했기 때문에 두 가지 증명 계층을 사용했습니다.

PoC 1: 자체 포함된 로컬 리졸버 데모

첫 번째 PoC는 근본 원인을 깔끔하게 분리했습니다.

다음을 수행하는 작은 로컬 하네스를 사용했습니다.

  • 127.0.0.1에서 루프백 HTTP 서버 시작
  • http://ssrf-repro.example:18080/...와 같은 URL 검증
  • 제어된 리졸버를 사용하여 ssrf-repro.example이 127.0.0.1로 확인되도록 함
  • 그런 다음 요청 수행

이는 정확한 결함을 입증했습니다.

  • 검증이 통과된 이유는 호스트명이 리터럴 차단 값이 아니었기 때문
  • 이후의 요청이 여전히 루프백에 도달함

캡처된 출력은 다음을 보여주었습니다.

  • 검증기 결과: 통과
  • 요청 실행 결과: 루프백 도달
  • 루프백 서비스에서 반환된 응답 본문

이는 검증 간격을 직접 증명했습니다.


PoC 2: 실제 Typebot 실행 경로

두 번째 PoC는 중요한 실제 기능 경로를 통해 버그를 보여주었습니다.

가장 간단한 재현 방법은 다음과 같습니다.

  1. Typebot 백엔드가 DNS를 확인하는 머신에서 무해한 호스트명을 루프백에 매핑
  2. 로컬 HTTP 서비스 시작
  3. 해당 무해한 호스트명을 가리키는 Webhook 블록 생성
  4. 정상적인 인증된 미리보기 또는 라이브 실행 경로를 통해 블록 트리거

대표적인 블록은 다음과 같습니다.

root@kitploit:~
{
  "id": "blk-webhook",
  "type": "Webhook",
  "options": {
    "webhook": {
      "method": "GET",
      "url": "http://ssrf-repro.example:8000/"
    }
  }
}

다음과 같은 hosts 파일 항목을 사용하여:

root@kitploit:~
127.0.0.1 ssrf-repro.example

검증기는 여전히 URL을 수락했습니다. 왜냐하면:

  • ssrf-repro.example이 blockedHostnames에 없음
  • localhost가 아님
  • parseIPAddress("ssrf-repro.example")이 null 반환
  • 대상 IP 검증이 발생하지 않음

그런 다음 백엔드 HTTP 클라이언트가 호스트명을 127.0.0.1로 확인하고 여전히 연결했습니다.

이는 전체 주장을 확립했습니다.

  • 취약한 검증 로직이 실제 기능 사용에서 도달 가능함
  • 요청이 차단된 대상 클래스에 도달함
  • 애플리케이션이 여전히 성공적인 아웃바운드 HTTP 요청으로 처리함

두 PoC가 이런 방식으로 선택된 이유

첫 번째 PoC는 근본 원인을 증명합니다.

두 번째 PoC는 제품 영향을 증명합니다.

그 구분이 중요합니다.

다음만 보여준다면:

"이 필터가 호스트명을 수락한다"

충분히 보여준 것이 아닙니다.

다음만 보여준다면:

"내부 요청이 발생했다"

왜 그런지 분리하지 않았습니다.

더 강력한 보고서는 다음과 같습니다.

  • 호스트명 기반 검증이 신뢰할 수 없었어야 할 값을 수락함
  • DNS 확인이 나중에 해당 값의 실제 보안 의미를 변경함
  • 백엔드가 차단된 대상에 연결함
  • 기능 경로가 여전히 완료됨

그것이 전체 이야기입니다.


심각도 및 분류

이 문제는 합리적으로 높음(High) 으로 분류되었습니다.

권고 분류는 다음과 같았습니다.

  • CWE-918: 서버 측 요청 위조(SSRF)
  • CWE-20: 부적절한 입력 검증
  • CVSS:
root@kitploit:~
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L

이는 타당합니다.

이것 자체만으로는 인증되지 않은 인터넷 전체 SSRF가 아니었습니다.

필요한 권한은 낮음(Low) 이었습니다. 독립형 버그는 Webhook / HTTP 요청 블록을 구성하거나 트리거할 수 있는 행위자가 필요했기 때문입니다.

그러나 해당 경계 내에서 영향은 심각했습니다.

  • 루프백 액세스
  • 사설 네트워크 액세스
  • 메타데이터 액세스
  • 로그를 통한 응답 유출

이는 그 자체로 강력한 SSRF 문제입니다.

그리고 도달 가능성을 넓히는 다른 버그와 결합되면 훨씬 더 위험해집니다.


이것이 여전히 보고할 가치가 있었던 이유

일부 사람들은 인증된 SSRF를 보고 즉시 과소평가합니다.

그것은 실수입니다.

진짜 질문은 다음과 같은 것이 아닙니다.

"공격자가 로그인했습니까?"

진짜 질문은 다음과 같습니다.

"그 공격자가 서버가 보안 모델이 금지하기로 되어 있는 곳에 연결하도록 할 수 있습니까?"

여기서 답은 '예'였습니다.

검증기는 보호한다고 주장했습니다.

  • 메타데이터 서비스
  • 루프백
  • RFC1918 사설 범위
  • IPv6 로컬 범위

그러나 호스트명 확인 간격으로 인해 동일한 대상이 다른 표현을 통해 다시 들어올 수 있었습니다.

이것이 바로 CVE를 받을 자격이 있는 버그 종류입니다.


수정 분석

실제 경계를 수정했기 때문에 수정은 견고했습니다. 단순한 증상이 아닙니다.

패치된 구현에서 validateHttpReqUrl()은 요청을 승인하기 전에 호스트명을 확인하도록 변경되었습니다.

이제 검증기는 다음을 수행합니다.

  • node:dns/promises에서 lookup 가져오기
  • 검증을 비동기로 처리
  • 허용하기 전에 리터럴이 아닌 호스트명 확인
  • 모든 확인된 주소 구문 분석
  • 동일한 차단 범위에 대해 모든 확인된 주소 검증

이는 신뢰 결정을 다음과 같이 변경하기 때문에 올바른 수정입니다.

  • "호스트명 텍스트가 괜찮아 보이는가?"

에서

  • "실제 대상이 허용된 주소로 확인되는가?"

로 변경되었습니다.

이는 처음부터 존재했어야 할 보안 속성입니다.

또한 수정 사항은 다음에 대한 회귀 테스트를 추가했습니다.

  • 루프백으로 확인되는 호스트명
  • RFC1918 공간으로 확인되는 호스트명
  • 자체 호스팅 사용자를 위한 허용된 내부 호스트
  • 메타데이터 및 루프백 대상에 대한 우회 불가능한 보호 유지

이것이 실제 SSRF 수정에서 원하는 종류의 강화입니다.

  • 경계가 수정됨
  • 의도된 동작이 코드에 문서화됨
  • 테스트가 해당 클래스를 고정함

이 문제는 Typebot 3.16.0에서 해결되었습니다.


공개

이 문제는 GitHub의 보안 보고 흐름을 통해 비공개로 보고되었습니다.

보고서에는 다음이 포함되었습니다.

  • validateHttpReqUrl()의 근본 원인
  • executeHttpRequest()의 다운스트림 실행 경로
  • 호스트명 확인을 루프백/사설 대상으로 사용하는 현실적인 재현 전략
  • 검증 간격을 분리하는 자체 포함 데모

유지 관리자가 문제를 수락하고 검증 로직을 수정했으며, 취약점은 나중에 다음과 같이 게시되었습니다.

CVE-2026-34207

수정 사항은 Typebot 3.16.0에서 릴리스되었습니다.


이 버그가 실제로 가르치는 교훈

핵심 교훈은 간단합니다.

보안 결정은 네트워크 스택이 실제로 사용할 동일한 표현에서 이루어져야 합니다.

당연해 보입니다.

그러나 많은 SSRF 보호가 정확히 그 규칙을 따르지 않기 때문에 실패합니다.

  • 호스트명 문자열은 안전해 보입니다.
  • DNS가 그 의미를 변경합니다.
  • 요청이 여전히 나갑니다.

그것으로 충분합니다.

이 버그는 또한 SSRF 검토 일반에 대해 중요한 점을 강화합니다.

  • 리터럴 IP 필터링만으로는 충분하지 않음
  • 호스트명 블랙리스트만으로는 충분하지 않음
  • 인코딩된 IP 검사만으로는 충분하지 않음

실제 대상을 확인하고 검증하지 않으면 SSRF 필터가 여전히 불완전합니다.

그것이 진짜 핵심입니다.


핵심 요점

  • SSRF 방어는 검증이 대상 확인 전에 발생할 때 실패합니다
  • 호스트명 텍스트 검증은 대상 IP 검증과 동일하지 않습니다
  • Webhook / HTTP 요청 기능은 실제 보안 경계입니다
  • 인증된 SSRF는 메타데이터 및 내부 서비스에 도달할 때 여전히 높은 심각도일 수 있습니다
  • 강력한 보고서는 근본 원인과 영향을 연결하며, 둘 중 하나만이 아닙니다
  • 수정이 올바른 이유는 결정을 실제 확인된 대상으로 이동했기 때문입니다

마지막 말

이 취약점은 화려한 페이로드에 관한 것이 아니었습니다.

올바른 경계 질문을 하는 것에 관한 것이었습니다.

Typebot에서 SSRF 검증기는 먼저 호스트명 텍스트를 확인했습니다. 실제 목적지는 나중에 DNS에 의해 결정되었습니다. 네트워크 클라이언트는 확인된 주소를 따랐습니다.

그 간격이 버그였습니다.

그것이 이 문제가 CVE-2026-34207이 된 이유입니다.

Typebot 3.16.0에서 수정되었습니다.

도구 다운로드