· 2 мин чтения
SSRF в вебхуках: проверка адреса после DNS
Почему сервис доставки вебхуков проверяет не строку URL, а адреса после разрешения DNS, и как hook-relay подключается именно к проверенному адресу.
Вебхук-сервис по определению ходит по адресам, которые ему дал пользователь. Значит, его можно попросить сходить на http://127.0.0.1, во внутреннюю сеть или к метаданным облака. Это SSRF.
Строка URL проверять бесполезно
Имя evil.example может указывать на 127.0.0.1, а публичный хост может вернуть и публичный, и приватный адрес. Поэтому hook-relay проверяет результат DNS, а не текст.
Что делает hook-relay
- Принимает только
httpиhttps, без логина и пароля в URL. - Разрешает хост через DNS и требует, чтобы все полученные адреса были публичными. Блокируются loopback, приватные диапазоны, link-local, CGNAT, документационные, ULA, IPv4-mapped, NAT64 и 6to4 с вложенным приватным адресом.
- Проверка идёт при регистрации получателя и снова при каждой доставке.
- Соединение устанавливается именно с проверенным адресом (в коде это
resolve(host, addr)для HTTP-клиента), поэтому между проверкой и подключением DNS нельзя подменить: защита от DNS rebinding.
Как это тестируется
Proptest: любой приватный IPv4 и его IPv4-mapped вид блокируются. Интеграционные тесты проверяют SSRF при регистрации и при доставке. Для самих тестов нужен приёмник на loopback, поэтому есть переменная HOOK_RELAY_ALLOW_PRIVATE_FOR_TESTS=1: она отключает защиту, в логе печатается предупреждение, и её нельзя включать нигде, кроме тестов.
Ограничения
Тело ответа получателя не читается и не сохраняется; доставка «минимум один раз», получатель должен быть идемпотентным. Сервис пока не развёрнут на сервере.