Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2026-34207 — Фильтр SSRF проверял текст имени хоста, но фактическое назначение определялось позже через DNS. Этот разрыв позволял управляемым злоумышленником URL-адресам Webhook достигать loopback, метаданных и целей частной сети. | Kitploit
Инструменты/GitHubGitHub/0xmrma/cve-2026-34207
Анализ уязвимостейЭксплуатацияВеб-безопасностьТестирование на ПроникновениеСтатьи и ИсследованияОбучение и Образование
GitHub0xmrma/cve-2026-34207

CVE-2026-34207

Фильтр SSRF проверял текст имени хоста, но фактическое назначение определялось позже через DNS. Этот разрыв позволял управляемым злоумышленником URL-адресам Webhook достигать loopback, метаданных и целей частной сети.

Репозиторий
63 месяцев назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2026-34207

Фильтр SSRF проверял текст имени хоста, но фактический адрес назначения определялся позже через DNS. Этот разрыв позволил URL-адресам вебхуков, контролируемым атакующим, достигать loopback, метаданных и частных сетевых целей.

Введение

Я обнаружил эту проблему во время проверки Typebot, открытого конструктора чат-ботов, задав простой вопрос безопасности:

Что происходит, если защита от SSRF проверяет текст имени хоста, а реальный адрес назначения определяется позже через DNS?

В данном случае этот вопрос привёл к реальной ошибке.

Защита от SSRF в Typebot для блоков Webhook / HTTP Request проверяла только:

  • строку URL,
  • заблокированные литералы имён хостов,
  • и литеральные форматы IP-адресов

Она не выполняла разрешение DNS-имён перед разрешением запроса.

Это означало, что имя хоста, например ssrf-repro.example, могло выглядеть безвредно при проверке, а затем разрешаться в:

  • 127.0.0.1
  • 169.254.169.254
  • или пространство RFC1918/частной сети

и всё равно быть загруженным HTTP-клиентом на серверной стороне.

Эта проблема стала CVE-2026-34207.

Typebot: Typebot на GitHub
CVE: CVE-2026-34207
Исправлено в: 3.16.0

Это затронуло Typebot, широко используемую платформу для создания чат-ботов с открытым исходным кодом. На официальном сайте Typebot представлен как продукт, которому доверяют более 650 компаний по всему миру. На сайте также рекламируются 2 млн+ чатов в месяц и 1,5 млн+ опубликованных ботов.

photo0

Цепочка атаки

URL вебхука, контролируемый атакующим -> имя хоста проходит проверку SSRF только на литералы -> принятие решения без разрешения DNS -> HTTP-клиент на серверной стороне разрешает имя хоста во внутреннюю цель -> серверный запрос достигает loopback / метаданных / частной сети -> данные ответа становятся доступны через журналы выполнения


Что делает Typebot

Typebot — это конструктор чат-ботов.

Он позволяет пользователям создавать сценарии, которые могут:

  • задавать вопросы
  • собирать структурированные данные
  • вызывать внешние сервисы
  • выстраивать бизнес-логику
  • и инициировать исходящие HTTP-запросы через блоки Webhook / HTTP Request

Таким образом, выполнение исходящих запросов — это реальная граница безопасности.

Важный вопрос здесь заключался не в том, поддерживает ли Typebot блоки Webhook.

Настоящий вопрос был таков:

Проверяет ли защита SSRF фактический адрес назначения, к которому подключится сервер, или только текст имени хоста, указанный в URL?

В данном случае сначала проверялась только текстовая форма.

Это и было ошибкой.


Почему эта поверхность стоила внимания

Защиты от SSRF терпят неудачу предсказуемым образом.

Чаще всего интересные ошибки — это не:

  • «вы забыли заблокировать 169.254.169.254»
  • или «вы забыли заблокировать localhost»

Более значимые ошибки — это ошибки границ:

  • проверка выполняется до канонизации
  • проверка выполняется до перенаправлений
  • проверка выполняется до разрешения DNS
  • проверка выполняется на одном представлении, а сетевая стек использует другое

Вот где стоило искать.

У Typebot уже была логика защиты от SSRF для литеральных IP-адресов метаданных, loopback, частных диапазонов и трюков с закодированными IP.

Это сделало следующий вопрос очевидным:

Что, если имя хоста не является буквально опасным, но позже разрешается в опасный адрес?

Именно это и произошло.


Первопричина

Корень проблемы — проверка адреса назначения по тексту имени хоста, а не по разрешённому IP-адресу.

В уязвимой реализации validateHttpReqUrl():

  • разбирала URL
  • разрешала только http: и https:
  • блокировала короткий список литеральных имён хостов, таких как metadata.google.internal, metadata.goog, metadata и localhost
  • обнаруживала трюки с литеральными десятичными / шестнадцатеричными / восьмеричными IP
  • разбирала литеральные IPv4 / IPv6 адреса
  • проверяла адрес только в том случае, если само имя хоста уже было литеральным IP

Это важная часть.

Если имя хоста было обычным значением, например:

ssrf-repro.example

то parseIPAddress(hostname) возвращал null, и проверка на этом останавливалась.

Перед одобрением не происходило разрешения DNS.

Таким образом, уязвимая логика фактически сводилась к:

const ip = parseIPAddress(hostname);
if (ip) {
  validateIPAddress(ip);
}

Это означает:

  • литеральные опасные IP блокировались
  • закодированные опасные IP блокировались
  • но имена хостов, разрешающиеся в опасные IP, — нет

Вторая половина ошибки находилась в пути выполнения.

В executeHttpRequest() Typebot сначала запускал проверку, а затем выполнял фактический запрос через ky(request.url, ...).

Таким образом, последовательность была такова:

  • проверить строку URL
  • принять имя хоста
  • позже разрешить имя хоста во время реального исходящего запроса
  • подключиться к разрешённой внутренней цели

Это и есть вся уязвимость.


Почему это проблема безопасности, а не просто неполная фильтрация

Важное различие — где принималось решение о доверии.

Многие ошибки выглядят мелкими, если их плохо описать.

Если описать эту ошибку как:

«фильтр имён хостов был неполным»

это звучит как проблема качества.

Но настоящая проблема заключалась в другом:

  • сервер принимал решение безопасности до того, как узнал реальный адрес назначения
  • сетевой стек позже подключался в другое место
  • и приложение считало такой запрос допустимым

Это не косметический недостаток фильтрации.

Это нарушение границы доверия.

И поскольку HTTP-исполнитель записывал данные ответа в журналы выполнения, проблема не была даже «слепой» в самых строгих случаях.

Так что это было не просто:

  • «произошёл неожиданный внутренний трафик»

Это было:

  • внутренний трафик произошёл
  • и атакующий часто мог получить подтверждение и содержимое ответа через нормальное поведение приложения

Это настоящая уязвимость SSRF.


Доказательство концепции

Я использовал два уровня доказательств, потому что они демонстрируют разные вещи.

PoC 1: самодостаточная демонстрация локального резолвера

Первый PoC чисто выделил первопричину.

Я использовал небольшой локальный стенд, который:

  • запускал HTTP-сервер loopback на 127.0.0.1
  • проверял URL вида http://ssrf-repro.example:18080/...
  • использовал управляемый резолвер, чтобы ssrf-repro.example разрешалось в 127.0.0.1
  • затем выполнял запрос

Это продемонстрировало точную ошибку:

  • проверка пройдена, потому что имя хоста не было литеральным заблокированным значением
  • последующий запрос всё равно достиг loopback

Зафиксированный вывод показал:

  • результат проверки: пройдено
  • результат выполнения запроса: достигнут loopback
  • тело ответа возвращено от сервиса loopback

Это напрямую доказывало пробел в проверке.


PoC 2: реальный путь выполнения Typebot

Второй PoC показал ошибку через фактический путь функции, который имеет значение.

Самое простое воспроизведение:

  1. Привязать безобидное имя хоста к loopback на машине, где серверная часть Typebot разрешает DNS
  2. Запустить локальный HTTP-сервис
  3. Создать блок Webhook, указывающий на это безобидное имя хоста
  4. Запустить блок через обычный аутентифицированный предварительный просмотр или путь выполнения в реальном времени

Примерный блок выглядел так:

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

С записью в файле hosts, например:

127.0.0.1 ssrf-repro.example

проверка всё равно принимала URL, потому что:

  • ssrf-repro.example не было в blockedHostnames
  • это не localhost
  • parseIPAddress("ssrf-repro.example") возвращал null
  • проверка IP адреса назначения не выполнялась
Скачать инструмент