Встала задача закрыть дыры в уже готовом PHP приложении(достаточно большом). После недолгих поисков убедился что единственным правильным решением для закрытия CSRF уязвимости является использование одноразовых токенов. Я поставил токены на все POST запросы, и все вроде-бы супер. Но!
Нигде толком не объясняется что делать, если таки придет запрос без токена. Где-то советуют отправлять «forbidden» где-то вообще 404. Как-бы можно и так. Но как быть с кнопкой F5? Там-то посылается уже устаревший токен.
Поиск например тоже проходит через POST. И если пользователь хочет повторить поиск, он обновляет страницу, и его выкидывает к черту на кулички. С точки зрения пользователя, это не совсем логично.
Так-же с историей браузера.
Eсли есть wizard, и пользователь возвращается на предыдущую страницу через кнопку «Back» браузера. Если его выкинуть на 404 или главную страницу, он потеряет все данные которые вводил.
Это только у меня такие проблемы? Кто-нибудь знает красивое решение?
Посмотрите как это реализовано в фрейворках. Например Symfony, YII и т.п.
Обычно логика следующая: в экшене контроллера с формой проверяем — если POST (значит идет сохранение формы), то проверяем токен. Если токен не совпадает, то просто не сохраняем данные, а отображаем ту же форму но с ошибкой «Неверный токен».
И токены обычно используются в формах при сохранении данных. Для формы поиска не вижу смысла их использовать.
Смысла для поиска конечно нет. Но приложение большое и форм много, поэтому я сделал проверку в BasicController, а там отличить POST поиска от других действий не такая тривиальная задача. Кроме того, даже для «не поиска» редирект по F5 на 404 мне не кажется удачной идеей. Странно что это во всех гайдах по CSRF рекомендуют.
> просто не сохраняем данные
Ну в принципе я почти так и сделал. В BasicController очищаю данные из POST, и показывается пустая форма. Но это как-то не очень красиво. Думал, может есть какое-нибудь _правильное_ решение.
Написано
Войдите на сайт
Чтобы задать вопрос и получить на него квалифицированный ответ.