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

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

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, метаданных и целей частной сети.

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

Популярное

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

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

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

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

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

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.

CVE-2026-34207

Typebot:
Typebot на GitHub

CVE:

Исправлено в:
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.

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

root@kitploit:~
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. Запустить блок через обычный аутентифицированный предварительный просмотр или путь выполнения в реальном времени

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

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 позже изменило реальное значение безопасности этого значения
  • серверная часть подключилась к заблокированному адресу назначения
  • и путь функции всё равно завершился

Это полная история.


Серьёзность и классификация

Эта проблема была обоснованно классифицирована как Высокая.

Классификация в уведомлении:

  • 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 сам по себе.

Требуемые привилегии были Низкими, потому что для отдельной ошибки требовался субъект, который мог настроить или запустить блок Webhook / HTTP Request.

Но в этих границах влияние было серьёзным:

  • доступ к loopback
  • доступ к частной сети
  • доступ к метаданным
  • и выгрузка ответов через журналы

Это сильная проблема SSRF сама по себе.

И она становится ещё опаснее в сочетании с другими ошибками, расширяющими охват.


Почему это всё равно стоило сообщить

Некоторые люди видят аутентифицированный SSRF и сразу занижают его оценку.

Это ошибка.

Настоящий вопрос не в том:

«Был ли атакующий авторизован?»

Настоящий вопрос в том:

«Мог ли этот атакующий заставить сервер подключиться туда, куда модель безопасности должна была запрещать?»

Здесь ответ — да.

Проверка утверждала, что защищает:

  • службы метаданных
  • loopback
  • частные диапазоны RFC1918
  • локальные диапазоны IPv6

Но пробел в разрешении имён хостов позволил тем же адресам назначения вернуться через другое представление.

Это именно та ошибка, которая заслуживает CVE.


Анализ исправления

Исправление было надёжным, потому что оно исправило реальную границу, а не просто симптом.

В исправленной реализации validateHttpReqUrl() была изменена на разрешение DNS-имён перед одобрением запроса.

Теперь проверка:

  • импортирует lookup из node:dns/promises
  • считает проверку асинхронной
  • разрешает нелитеральные имена хостов перед их разрешением
  • анализирует каждый разрешённый адрес
  • проверяет каждый разрешённый адрес на соответствие тем же заблокированным диапазонам

Это правильное исправление, потому что оно меняет решение о доверии с:

  • «выглядит ли текст имени хоста нормально?»

на:

  • «разрешается ли фактический адрес назначения в разрешённый адрес?»

Это свойство безопасности, которое должно было существовать с самого начала.

Исправление также добавило регрессионные тесты для:

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

Это тот вид усиления, который вы хотите видеть в реальном исправлении SSRF:

  • граница исправлена
  • ожидаемое поведение задокументировано в коде
  • и тесты фиксируют класс ошибок

Проблема была исправлена в Typebot 3.16.0.


Раскрытие

Эта проблема была сообщена приватно через поток безопасности на GitHub.

Отчёт включал:

  • первопричину в validateHttpReqUrl()
  • последующий путь выполнения в executeHttpRequest()
  • реалистичную стратегию воспроизведения с использованием разрешения имени хоста в loopback / частные цели
  • и самодостаточную демонстрацию для изоляции пробела в проверке

Сопровождающие приняли проблему, исправили логику проверки, и уязвимость позже была опубликована как:

CVE-2026-34207

с исправлением, выпущенным в Typebot 3.16.0.


Чему на самом деле учит эта ошибка

Ключевой урок прост:

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

Это звучит очевидно.

Но многие защиты SSRF терпят неудачу именно потому, что не следуют этому правилу.

  • Строка имени хоста выглядит безопасной.
  • DNS меняет её значение.
  • Запрос всё равно отправляется.

Этого достаточно.

Эта ошибка также подкрепляет важный момент при анализе SSRF в целом:

  • фильтрация литеральных IP недостаточна
  • чёрные списки имён хостов недостаточны
  • проверки закодированных IP недостаточны

Если вы не разрешаете и не проверяете реальный адрес назначения, ваш фильтр SSRF всё ещё неполон.

Вот настоящий вывод.


Ключевые моменты

  • Защита SSRF терпит неудачу, когда проверка выполняется до разрешения адреса назначения
  • Проверка текста имени хоста — это не то же самое, что проверка IP-адреса назначения
  • Функции Webhook / HTTP Request — это реальные границы безопасности
  • Аутентифицированный SSRF всё ещё может быть высокой степени серьёзности, когда он достигает метаданных и внутренних служб
  • Сильный отчёт связывает первопричину и влияние, а не только одно из них
  • Исправление было правильным, потому что оно перенесло решение на фактический разрешённый адрес назначения

Заключительные слова

Эта уязвимость не была связана с хитрой полезной нагрузкой.

Она заключалась в постановке правильного вопроса о границах.

В Typebot проверка SSRF сначала проверяла текст имени хоста. Фактический адрес назначения определялся позже через DNS. Сетевой клиент следовал разрешённому адресу.

Этот разрыв и был ошибкой.

Вот почему это стало CVE-2026-34207.

Исправлено в Typebot 3.16.0.

Скачать инструмент