Как использовать timestamp для защиты от replay-атак
Как защититься от replay-атак с помощью простой настройки на бэкенде.
Суть кратко
DFP передаёт в расшифрованном payload поле timestamp — время, когда был сформирован результат.
Проверяйте timestamp на своём бэкенде. Если ответ старше несколько секунд относительно текущего времени UTC, не используйте его. Так вы защититесь от replay-атаки (атаки повторного воспроизведения): ситуации, когда старый ответ DFP пытаются отправить повторно как свежий, чтобы эксплуатировать ваш сервис.
Как может произойти replay-атака
Все ответы DFP проходят через браузер пользователя: сначала DFP возвращает ответ браузеру, а потом скрипт в браузере отправляет этот ответ на ваш бэкенд. Именно браузер здесь слабое место: в нём можно попытаться подменить свежий ответ DFP на старый.
Например, злоумышленник хочет автоматически собирать данные с вашего сайта: отслеживать цены, наличие товаров или свободные слоты для записи.
Вы разрешаете обычным пользователям открывать эти страницы, а вот для запросов с высоким bot_score уже настроили блокировку, чтобы защититься от парсинга.
Злоумышленник делает так:
-
Открывает сайт в обычном браузере с нормального IP-адреса.
-
Получает настоящий ответ DFP для чистого окружения: обычный браузер, не датацентр, не автоматизация, низкий
bot_score. -
Сохраняет полный ответ DFP.
-
Запускает автоматизацию: скрипт, который отправляет большое количество запросов.
-
При каждом запросе подставляет сохранённый ответ DFP вместо свежего ответа, который был бы получен в автоматизированном окружении.
-
Если бэкенд не проверяет
timestamp, он может принять старый ответ как результат текущей проверки и решить, что запрос пришёл от обычного пользователя. -
В итоге запросы не блокируются, и злоумышленник продолжает массово собирать данные с сайта.
DFP передаёт в payload поле timestamp, поэтому вы можете проверить свежесть ответа и не принимать один и тот же результат повторно.
Как защититься
Проверяйте timestamp после расшифровки payload.
Проверку должен выполнять ваш бэкенд. Не используйте время из браузера: его можно подменить. Опирайтесь только на timestamp.
Ваш бэкенд:
-
Получает ответ DFP от браузера.
-
Расшифровывает payload.
-
Читает
timestamp. -
Сравнивает
timestampс текущим временем UTC. -
Если ответ свежий — продолжает обработку. Если слишком старый — отклоняет его.
Пример политики:
const MAX_DFP_RESPONSE_AGE_MS = 5_000;
const responseTimestamp = Date.parse(payload.timestamp);
const responseAge = Date.now() - responseTimestamp;
if (
!Number.isFinite(responseTimestamp) ||
responseAge < 0 ||
responseAge > MAX_DFP_RESPONSE_AGE_MS
) {
throw new Error('DFP response is expired');
}
acceptDfpResult(payload);
Допустимое окно «свежести» timestamp определяете вы в соответствии со своим бизнес-сценарием.