CSRF: Как предотвратить уязвимость

Источник: «How to prevent CSRF vulnerabilities»
В этой статье мы рассмотрим какие есть средства защиты от CSRF уязвимости и как правильно их реализовать на своём сайте для предотвращения уязвимости.

Используйте CSRF токены

Самый надёжный способ защиты от CSRF-атак — включение CSRF токена в соответствующие запросы. Токен должен соответствовать следующим критериям:

Как должны генерироваться CSRF токены

CSRF токены должны содержать значительную энтропию и быть непредсказуемыми, с теми же свойствами, что и токены сеанса в целом.

Нужно использовать криптографически безопасный генератор псевдослучайных чисел (CSPRNG), засеянный отметкой времени, когда он был создан плюс статический секретный ключ.

Если нужна дополнительная гарантия, выходящая за пределы CSPRNG, можно сгенерировать отдельные токены, объединив их вывод с некоторой пользовательской энтропией и получить сильный хэш всей структуры. Это создаст дополнительный барьер для злоумышленника, который попытается проанализировать токены на основе выданного ему образца.

Как передавать CSRF токены

CSRF токены должны рассматриваться как секрет и обрабатываться безопасным способом на протяжении всего их жизненного цикла. Эффективный подход заключается в передаче токена клиенту в скрытом поле HTML-формы, которая отправляется с использованием метода POST. Затем токен включается в качестве параметра запроса при отправке формы:

<input type="hidden" name="csrf-token" value="CIwNZNlR4XbisJF39I8yWnWX9wX4WFoz" />

Для дополнительной безопасности поле содержащее CSRF токен следует разместить в HTML-документе как можно раньше. В идеале перед любыми не скрытыми полями ввода и перед любыми местами, где данные контролируемые пользователем встроены в HTML. Этот защищает от различных методов, с помощью которых злоумышленник может использовать созданные данные для манипулирования HTMl-документом и захватом частей его содержимого.

Альтернативный подход с размещением маркера в строке запроса URL менее безопасен, поскольку строка запроса:

Некоторые приложения передают CSRF токены в пользовательском заголовке запроса. Это даёт дополнительную защиту от злоумышленника, которому удаётся предсказать или захватить токен другого пользователя, поскольку браузеры обычно не позволяют отправлять пользовательские заголовки между доменами. Однако этот подход ограничивает приложение выполнением CSRF защищённых запросов с использованием XHR (в отличие от HTML-форм) и во многих ситуациях может показаться чрезмерно сложным.

CSRF токены не должны передаваться в файлах cookie.

Как проверять CSRF токены

Когда CSRF токен сгенерирован, он должен храниться на стороне сервера в данных сеанса пользователя. Когда получен последующий запрос, требующий проверки, приложение на стороне сервера должно убедиться, что запрос включает токен, соответствующий значению, которое было сохранено в сеансе пользователя. Эта проверка должна выполняться независимо от HTTP метода или типа содержимого запроса. Если запрос вообще не содержит токена, он должен быть отклонён так же как и в случае наличия не валидного токена.

Используйте строгие ограничения cookie SameSite

Помимо реализации надёжной проверки CSRF токена рекомендуется явно устанавливать собственные ограничения SameSite для каждого файла cookie, который вы создаёте. Таким образом, вы можете контролировать в каких контекстах будет использовать файл cookie, независимо от браузера.

Даже если все браузеры примут политику Lax-by-default, это не подходит для каждого файла cookie, и её легче обойти, чем Strict ограничения. В то же время несоответствие между различными браузерами также означает, что только часть ваших пользователей вообще получит выгоду от SameSite защиты.

В идеале должна использоваться политика Strict по умолчанию, а затем снижать её до Lax, только если есть причина. Никогда не отключайте ограничения SameSite с помощью SameSite=None, если вы полностью не осведомлены о последствиях для безопасности.

Остерегайтесь cross-origin, same-site атак

Хотя правильно настроенные ограничения SameSite обеспечивают хорошую защиту от межсайтовых атак, важно понимать, что они совершенно бессильны против cross-origin, same-site атак.

Если возможно, рекомендуется изолировать небезопасный контент, например загружаемые пользователем файлы, на отдельном сайте от любых конфиденциального функционала или данных. При тестировании сайта обязательно тщательно проверьте все доступные поверхности атак, принадлежащие этому сайту, включая любые из его родственных доменов.

Дополнительные материалы

Предыдущая Статья

Laravel: Web и API — одинаковые или разные контроллеры?

Следующая Статья

Laravel: Eloquent create() vs Query Builder insert()