Webhooks: безопасность¶
Что делаем мы¶
Подпись HMAC-SHA256¶
Каждый webhook содержит заголовок X-Truenum-Signature: t=<ts>,v1=<hex>.
Без проверки подписи нельзя доверять телу — атакующий, узнавший
ваш webhook_url (а это не секретная информация), сможет отправить
поддельный POST. Полная инструкция: Подпись.
SSRF-защита webhook_url¶
При создании верификации мы валидируем URL:
- Схема — только
httpилиhttps. - Хост — только публичный IP / DNS-имя, резолвящееся в публичный IP.
- Запрещены:
127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16(link-local),::1,fc00::/7,fe80::/10, а также0.0.0.0. - Запрещены любые DNS-имена, резолвящиеся в приватный диапазон.
Если URL не проходит проверку — 400 Bad Request с конкретным
сообщением.
Анти-DNS-rebind¶
DNS-имя может разрешиться в публичный IP в момент валидации и в
приватный в момент доставки. Поэтому валидация выполняется
дважды: при POST /verifications/ и непосредственно перед каждой
попыткой доставки. На стороне нашей инфраструктуры использование
requests + custom HTTPAdapter гарантирует resolve-once и проверку
финального IP перед открытием соединения.
Таймаут¶
Мы ждём ответа 10 секунд. Дольше — закрываем соединение, считаем попытку проваленной (см. Ретраи).
User-Agent¶
User-Agent: TrueNum/1.0. Идентифицирует нас в логах и позволяет
вам whitelisted'ить только реальный трафик (но не используйте
User-Agent для аутентификации — его легко подделать; полагайтесь
на подпись).
Egress IP¶
Мы можем менять egress-IP без предупреждения. Не whitelisted'те IP для аутентификации входящих webhook'ов — используйте подпись.
Что должны делать вы¶
Проверка подписи¶
Обязательно. Подробно — Подпись.
Защита от replay¶
Сравните t (timestamp в подписи) с текущим временем. Если разница
5 минут — отклоните. Это защищает от reply-атак злоумышленником, у которого есть запись валидного webhook'а.
HTTPS¶
webhook_url должен быть HTTPS. Сертификат — валидный (не self-signed),
выданный публичной CA. Это защищает тело + подпись от
прослушки/модификации на сетевом уровне.
Идемпотентность приёма¶
См. Ретраи. Один и тот же webhook может прилететь несколько раз — ваш обработчик должен быть готов.
Аутентификация эндпоинта на вашей стороне¶
Webhook-эндпоинт должен быть публичным (ниже — почему). При этом аутентификация осуществляется через подпись webhook'а, не через бэйсик-ауф / OAuth. Не выдавайте webhook-эндпоинт за приватный ресурс с защитой по сети — это противоречит SSRF-протоколу: мы специально отказываемся ходить в приватные сети.
Не парсите JSON до проверки подписи¶
Парсер JSON — тоже потенциальная attack-surface (особенно в нестрого-типизированных языках). Сначала проверьте подпись, потом парсите.
Логирование¶
Логируйте каждый прилетевший webhook (включая отброшенные по подписи) с: timestamp, hash подписи, размер тела, ваш ответ. Без тела — тела могут содержать персональные данные. Срок хранения — по вашему compliance.
Чего НЕ делаем¶
- Не указываем
webhook_urlили содержимое тела в общедоступных логах TrueNum. Журнал доставок виден только владельцу аккаунта в дашборде. - Не отправляем
client_refилиphoneтретьим сторонам. Они возвращаются только в вашwebhook_url. - Не следуем HTTP-редиректам (3xx → ретрай как ошибка).
webhook_urlдолжен быть финальным.
Если подозреваете компрометацию¶
- Ротируйте webhook secret в дашборде — старый секрет инвалидируется немедленно. Все приходящие webhook'и теперь подписываются новым.
- Обновите секрет на стороне приёмника.
- Просмотрите дашборд Webhooks → Deliveries — есть ли
аномальные
2xx-ответы от чужой инфраструктуры (это возможно только если злоумышленник перехватилwebhook_url, что само по себе требует расследования). - Если подозреваете утечку API-ключа — ротируйте и его (см. Аутентификация).