Клиент повторно отправляет ранее корректный запрос на изменение лимита, перехваченный в сети. Как защитить операцию от повторного воспроизведения?
Нужно добавить к запросу проверяемую свежесть: одноразовый идентификатор, счётчик или ограниченный по времени идентификатор запроса, а сервер должен атомарно отслеживать уже использованные значения. Эти данные необходимо защищать подписью или иным механизмом целостности, связывая их с конкретной операцией.
Одного TLS недостаточно: он защищает канал передачи, но не предотвращает повторную отправку уже полученного корректного запроса. Одного идентификатора идемпотентности тоже может быть недостаточно, если требуется именно обнаруживать атаку, а не только устранять повторный эффект.
Защита от повторного воспроизведения появилась как часть протоколов аутентификации и платёжных систем. Перехваченный запрос мог быть полностью подлинным, поэтому проверка подписи или пароля сама по себе не доказывала, что сообщение новое.
Для решения этой проблемы применяют одноразовые значения, временные метки, счётчики и challenge-response-механизмы. Они добавляют к проверке подлинности проверку актуальности сообщения.
Злоумышленник может получить копию корректного запроса из журнала, скомпрометированного клиента, промежуточного компонента или конечной точки. Если сервер проверяет только подпись и полномочия отправителя, он примет копию как новый запрос.
Для операции изменения лимита это может привести к повторному применению действия, нарушению бизнес-ограничений или обходу предполагаемой последовательности операций. Особенно опасны неидемпотентные действия: списание средств, выпуск прав, изменение настроек и отправка команд.
Практический вариант — включать в подписываемый запрос уникальный идентификатор, время создания и, при необходимости, срок действия. Сервер проверяет подпись, допустимое временное окно и то, что данный идентификатор ещё не использовался.
Проверка должна быть связана с контекстом операции: идентификатор нельзя принимать повторно для другого метода, ресурса, клиента или набора параметров. Подпись должна покрывать как саму команду, так и её идентификатор, время, адресата и значимые параметры; иначе злоумышленник сможет перенести свежий идентификатор в другой запрос.
Ключевая техническая деталь — проверка уникальности и фиксация использования должны выполняться атомарно. Иначе два параллельных повтора могут одновременно пройти проверку до того, как любой из них отметит идентификатор использованным.
В распределённой системе состояние использованных идентификаторов должно быть доступно всем узлам, обрабатывающим операцию, либо запросы должны маршрутизироваться с гарантией сохранения состояния. Записи обычно хранят ограниченное время, соответствующее максимальному сроку действия запроса, но слишком короткий срок увеличивает риск принятия повтора.
Временная метка уменьшает объём состояния, однако требует синхронизации часов и допуска на сетевую задержку. Поэтому она ограничивает окно атаки, но сама по себе не гарантирует одноразовость: один и тот же запрос можно повторить внутри допустимого окна.
Идемпотентность полезна как дополнительная мера: сервер связывает ключ запроса с результатом и возвращает тот же результат при повторе. Это защищает бизнес-эффект от дублей, но не всегда обнаруживает злоумышленника и не заменяет проверку подлинности, свежести и полномочий.
Сервис управления платежными лимитами принимает подписанные команды от клиентского приложения. Команда содержит новый лимит и уникальный идентификатор операции. После перехвата злоумышленник повторяет её несколько раз.
Вариант только с TLS не подходит: он защищает передачу, но не доверенный конечный узел и не предотвращает повтор уже принятого сообщения. Вариант только с временной меткой дешевле по состоянию, но оставляет окно для повторов и зависит от корректности часов.
Выбранное решение — подпись команды с привязкой к клиенту, операции, параметрам и уникальному идентификатору, а также атомарная регистрация идентификатора в общем хранилище. Для безопасных повторных отправок из-за сетевых сбоев дополнительно используется идемпотентное возвращение ранее сохранённого результата.
В результате повторная команда не выполняется второй раз: первый запрос резервирует идентификатор, а последующие отклоняются или получают сохранённый результат. Параллельная обработка также не создаёт два изменения благодаря атомарной операции регистрации.
Нет, не всегда. Идемпотентный ключ предотвращает повторный бизнес-эффект, если сервер надёжно хранит связь ключа с результатом, но он не обязательно доказывает, что запрос отправил ожидаемый субъект и что запрос актуален.
Если злоумышленник может повторить запрос с тем же ключом, система может корректно вернуть прежний результат, но сам факт атаки останется незамеченным. Поэтому для чувствительных действий нужны совместно аутентификация, проверка полномочий, контроль свежести и идемпотентность.
Одинаковый запрос остаётся действительным для всех повторов в пределах разрешённого окна. Чем больше окно, тем выше вероятность успешного повтора; чем оно меньше, тем чаще будут отказы из-за задержек и рассинхронизации часов.
Временная метка хорошо ограничивает срок действия сообщения, но не обеспечивает уникальность. Для строгой одноразовости её сочетают с идентификатором, который сервер атомарно помечает использованным, либо с монотонным счётчиком.
Недостаточно сначала проверить отсутствие идентификатора, а затем отдельной операцией записать его. Два экземпляра могут одновременно выполнить проверку и оба начать обработку.
Нужна единая для всех экземпляров координация: атомарная операция добавления с условием уникальности, транзакция в согласованном хранилище или другой механизм, гарантирующий, что только один обработчик успешно зарегистрирует идентификатор. Запись следует создавать до необратимого побочного эффекта либо связывать её с этим эффектом транзакционно; иначе сбой между двумя шагами может привести к повторному выполнению или к невозможности безопасно повторить запрос.