Как предотвращать уязвимости CSRF
Используйте CSRF-токены
Самый надёжный способ защиты от CSRF-атак — включать CSRF-токен в соответствующие запросы. Токен должен удовлетворять следующим критериям:
Непредсказуемость и высокая энтропия, как и для сессионных токенов в целом.
Привязка к пользовательской сессии.
Строгая проверка в каждом случае до выполнения соответствующего действия.
Как генерировать CSRF-токены?
CSRF-токены должны иметь значительную энтропию и быть криптографически непредсказуемыми, с теми же свойствами, что и сессионные токены в целом. Используйте криптографически стойкий генератор псевдослучайных чисел — CSPRNG (cryptographically secure pseudo-random number generator), инициализированный отметкой времени создания плюс статическим секретом.
Если требуется дополнительная надёжность сверх стойкости CSPRNG, вы можете генерировать отдельные токены, конкатенируя его вывод с некоторой пользовательской энтропией и вычисляя стойкий хэш всей конструкции. Это создаёт дополнительный барьер для атакующего, который пытается анализировать токены по выборке выданных ему значений.
Как передавать CSRF-токены?
CSRF-токены следует рассматривать как секреты и безопасно обрабатывать на всём протяжении их жизненного цикла. Обычно эффективный подход — передавать токен клиенту в скрытом поле HTML-формы, отправляемой методом POST. Тогда токен будет включён в запрос как параметр при отправке формы:
<input type="hidden" name="csrf-token" value="CIwNZNlR4XbisJF39I8yWnWX9wX4WFoz" />Для дополнительной безопасности поле с CSRF-токеном следует размещать как можно раньше в HTML-документе, желательно до любых нескрытых полей ввода и до мест, где в HTML внедряются данные, контролируемые пользователем. Это снижает эффективность различных техник, при которых атакующий с помощью специально сформированных данных может манипулировать HTML-документом и перехватывать части его содержимого.
Альтернативный подход — помещать токен в строку запроса URL — несколько менее безопасен, поскольку строка запроса:
Логируется в разных местах на стороне клиента и сервера
Может передаваться третьим сторонам в HTTP-заголовке Referer
Может отображаться на экране в браузере пользователя.
Некоторые приложения передают CSRF-токены в пользовательском заголовке запроса. Это даёт дополнительную защиту от атакующего, сумевшего предсказать или перехватить токен другого пользователя, поскольку браузеры обычно не позволяют отправлять пользовательские заголовки Cross-Domain. Однако такой подход ограничивает приложение выполнением защищённых от CSRF запросов с помощью XHR (XMLHttpRequest) (в отличие от HTML-форм) и может оказаться чрезмерно сложным во многих ситуациях.
CSRF-токены не следует передавать в составе cookie.
Как проверять CSRF-токены?
При генерации CSRF-токена его нужно сохранить на сервере в данных сессии пользователя. Когда поступает следующий запрос, требующий проверки, серверное приложение должно убедиться, что запрос содержит токен, совпадающий со значением, сохранённым в сессии пользователя. Эта проверка должна выполняться независимо от метода HTTP или типа содержимого запроса. Если запрос вовсе не содержит токена, его следует отклонить так же, как при наличии недействительного токена.
Используйте строгие ограничения SameSite для cookie
В дополнение к надёжной проверке CSRF-токенов рекомендуем явно задавать собственные ограничения SameSite для каждого устанавливаемого cookie. Так вы сможете точно контролировать, в каких контекстах будет использоваться cookie, независимо от браузера.
Даже если все браузеры в итоге примут политику «Lax по умолчанию», она подходит не для каждого cookie и проще, чем ограничения Strict. Между тем несоответствие поведения разных браузеров означает, что только часть ваших пользователей вообще получит выгоду от ограничений SameSite.
В идеале следует использовать политику Strict по умолчанию, а понижать её до Lax только при наличии веских причин. Никогда не отключайте ограничения SameSite через SameSite=None, если вы не полностью осознаёте последствия для безопасности.
Остерегайтесь Cross-Origin атак в рамках одного сайта (same-site)
Хотя корректно настроенные ограничения SameSite хорошо защищают от Cross-Site атак, важно понимать, что они совершенно бессильны против Cross-Origin атак в рамках одного сайта (same-site).
По возможности рекомендуем изолировать небезопасный контент, такой как загружаемые пользователями файлы, на отдельном сайте от любого чувствительного функционала или данных. При тестировании сайта обязательно тщательно проверяйте всю доступную поверхность атаки, принадлежащую тому же сайту, включая любые его родственные домены.
Last updated