Как правильно использовать CSRF токены?

Встала задача закрыть дыры в уже готовом PHP приложении(достаточно большом). После недолгих поисков убедился что единственным правильным решением для закрытия CSRF уязвимости является использование одноразовых токенов. Я поставил токены на все POST запросы, и все вроде-бы супер. Но!

Нигде толком не объясняется что делать, если таки придет запрос без токена. Где-то советуют отправлять «forbidden» где-то вообще 404. Как-бы можно и так. Но как быть с кнопкой F5? Там-то посылается уже устаревший токен.

Поиск например тоже проходит через POST. И если пользователь хочет повторить поиск, он обновляет страницу, и его выкидывает к черту на кулички. С точки зрения пользователя, это не совсем логично.
Так-же с историей браузера.
Eсли есть wizard, и пользователь возвращается на предыдущую страницу через кнопку «Back» браузера. Если его выкинуть на 404 или главную страницу, он потеряет все данные которые вводил.

Это только у меня такие проблемы? Кто-нибудь знает красивое решение?
  • Вопрос задан
  • 25462 просмотра
Пригласить эксперта
Ответы на вопрос 5
SSiarhei
@SSiarhei
У нас лично токен выдается на логине и хранится в сессии. Зачем каждый раз токен новый генерить?
Ответ написан
@egorinsk
Токен достаточно иметь один на сессию. При несовпадении токена надо показать сообщение «Произошла ошибка. Пожалуйста, проверьте введенные данные, и отправьте форму еще раз».

Естественно, сообщение надо показать вместе с формой с заполненными данными, а не на пустой стрнаице.

GET-формы, не вносящие изменений в базу данных, вроде формы поиска, не надо защищать.
Ответ написан
Комментировать
stnw
@stnw
Посмотрите как это реализовано в фрейворках. Например Symfony, YII и т.п.
Обычно логика следующая: в экшене контроллера с формой проверяем — если POST (значит идет сохранение формы), то проверяем токен. Если токен не совпадает, то просто не сохраняем данные, а отображаем ту же форму но с ошибкой «Неверный токен».
И токены обычно используются в формах при сохранении данных. Для формы поиска не вижу смысла их использовать.
Ответ написан
rasstroen
@rasstroen
Не обновляйте токен после каждого запроса, выставляйте его вместе с авторизационными куками.
Про F5 — можно переводить header(Location:/) после запроса там, где это уместно, или использовать AJAX с тем же токеном
Ответ написан
Комментировать
slider
@slider Автор вопроса
Клиент в поиске может указать какие-то личные данные, которые не должны попасть к третьему лицу, не зависимо от того, что сними будет дальше, Поэтому они не должны попадать в URL (GET).
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы