· 2 мин чтения

SSRF в вебхуках: проверка адреса после DNS

Почему сервис доставки вебхуков проверяет не строку URL, а адреса после разрешения DNS, и как hook-relay подключается именно к проверенному адресу.

Проект: hook-relay

Вебхук-сервис по определению ходит по адресам, которые ему дал пользователь. Значит, его можно попросить сходить на http://127.0.0.1, во внутреннюю сеть или к метаданным облака. Это SSRF.

Строка URL проверять бесполезно

Имя evil.example может указывать на 127.0.0.1, а публичный хост может вернуть и публичный, и приватный адрес. Поэтому hook-relay проверяет результат DNS, а не текст.

Что делает hook-relay

  1. Принимает только http и https, без логина и пароля в URL.
  2. Разрешает хост через DNS и требует, чтобы все полученные адреса были публичными. Блокируются loopback, приватные диапазоны, link-local, CGNAT, документационные, ULA, IPv4-mapped, NAT64 и 6to4 с вложенным приватным адресом.
  3. Проверка идёт при регистрации получателя и снова при каждой доставке.
  4. Соединение устанавливается именно с проверенным адресом (в коде это resolve(host, addr) для HTTP-клиента), поэтому между проверкой и подключением DNS нельзя подменить: защита от DNS rebinding.

Как это тестируется

Proptest: любой приватный IPv4 и его IPv4-mapped вид блокируются. Интеграционные тесты проверяют SSRF при регистрации и при доставке. Для самих тестов нужен приёмник на loopback, поэтому есть переменная HOOK_RELAY_ALLOW_PRIVATE_FOR_TESTS=1: она отключает защиту, в логе печатается предупреждение, и её нельзя включать нигде, кроме тестов.

Ограничения

Тело ответа получателя не читается и не сохраняется; доставка «минимум один раз», получатель должен быть идемпотентным. Сервис пока не развёрнут на сервере.