Понимание CSRF в глубину
Представляет собой глубокое исследование атак однонаправленной подделки запросов (CSRF), объясняя их механику, демонстрируя примеры и подробно описывая различные методы предотвращения для повышения безопасности веб-приложений.
При работе над веб-разработкой, особенно с куки, мы часто слышим такие фразы, как "эта настройка помогает предотвратить CSRF". Однако многие люди имеют лишь смутное представление о том, что на самом деле означает "CSRF".
Сегодня мы углубимся в CSRF (однонаправленная подделка запросов), распространённую уязвимость безопасности веба. Это поможет нам более эффективно справляться с проблемами, связанными с CSRF.
Что такое CSRF?
CSRF (однонаправленная подделка запросов) – это тип веб-атаки, в которой злоумышленники обманывают аутентифицированных пользователей, заставляя их выполнять непреднамеренные действия. Проще говоря, это "хакеры, выдающие себя за пользователей для выполнения несанкционированных действий".
Как работает CSRF
Чтобы понять CSRF, нам нужно ухватить несколько ключевых концепций:
Политика того же происхождения браузера
Политика того же происхождения – это функция безопасности в браузерах, которая ограничивает, как документ или скрипт из одного источника может взаимодействовать с ресурсами из другого источника.
Происхождение состоит из протокола (например, HTTP или HTTPS), доменного имени и номера порта. Например, https://example.com:443
– это одно происхождение, в то время как https://demo.com:80
– другое.
Политика того же происхождения ограничивает доступ к данным между страницами из разных источников, имея в виду:
- JavaScript из одного происхождения не может читать DOM другого происхождения
- JavaScript из одного происхождения не может читать Cookie, IndexedDB или localStorage другого происхождения
- JavaScript из одного происхождения не может отправлять AJAX-запросы на другой источник (кроме как с использованием CORS)
Однако, чтобы поддерживать открытость и интероперабельность веба (например, загрузка ресурсов из CDN или отправка запросов к сторонним API для регистрации), политика того же происхождения не ограничивает перекрёстные сетевые запросы:
- Страницы могут отправлять GET или POST-запросы на любое происхождение (например, загрузка изображений или отправка форм)
- Ресурсы из любого происхождения могут включаться (например, теги
<script>
,<img>
,<link>
,<iframe>
)
Механизм автоматической отправки куки
Механизм автоматической отправки куки – это важная функция браузеров. Когда браузер отправляет запрос к домену, он автоматически прикрепляет все куки для этого домена. Этот процесс автоматический и не требует какого-либо JavaScript-кода или взаимодействия пользователя.
Этот механизм позволяет веб-сайтам легко запоминать состояние входа пользователей, так как каждый запрос автоматически несёт информацию о личности пользователя.
Жирный
Например, когда вы входите на банковский сайт (bank.com
) и получаете идентификационную куки, затем, когда вы нажимаете для просмотра выписки, браузер автоматически находит все куки, соответствующие bank.com
, и прикрепляет их к запросу выписки. Сервер банка может затем идентифицировать вас на стороне сервера и вернуть вашу информацию о выписке.
Этапы атаки CSRF
-
Пользователь входит на целевой веб-сайт (например, сайт банка) и получает аутентификационную куки. Этот шаг использует механизм автоматической отправки куки. После того как сайт банка устанавливает куки аутентификации, браузер будет автоматически прикреплять эту куки к каждому запросу, отправленному на этот сайт.
-
Не выходя из системы, пользователь посещает вредоносный сайт. На данный момент, из-за политики того же происхождения, вредоносный сайт не может напрямую читать или изменять куки сайта банка. Это защищает информацию личности пользователя от прямого похищения.
-
Вредоносный сайт включает запрос на целевой сайт (например, операцию перевода). Хотя политика того же происхождения ограничивает перекрёстный доступ, она позволяет перекрёстные сетевые запросы, такие как запросы, инициированные через теги
<img>
,<form>
. Злоумышленники используют эту "уязвимость". -
Браузер пользователя автоматически отправляет этот запрос вместе с куки целевого сайта. Это ядро атаки CSRF. Она использует одновременно политику того же происхождения, позволяющую перекрёстные запросы, и механизм автоматической отправки куки (даже запросы, инициированные вредоносными сайтами, возьмут куки, соответствующие домену).
-
Целевой сайт получает запрос, проверяет, что куки действительны, и выполняет операцию. Сервер не может определить, исходит ли этот запрос от законного действия пользователя, т.к. прикреплённая куки действительна.
Пример атаки CSRF
Давайте проиллюстрируем, как происходит атака CSRF на конкретном примере. Воспользуемся вымышленным банковским сайтом bank.com
.
Сначала пользователь посещает https://bank.com
и входит в свой аккаунт.
После успешного входа сервер устанавливает аутентификационную куки, например:
Пользователь выполняет операцию перевода на банковском сайте, скажем, переводя $1000 Алисе. Эта операция может отправить запрос, подобный этому:
Теперь предположим, что злоумышленник создаёт вредоносный сайт https://evil.com
, содержащий следующий HTML:
Когда пользователь нажимает на ссылку https://evil.com
не выходя из своей банковской учётной записи, поскольку он уже вошёл на bank.com
, браузер имеет действительную куки session_id
.
После того как вредоносная страница загружается, она автоматически отправляет скрытую форму, отправляя запрос на перевод на https://bank.com/transfer
.
Браузер пользователя автоматически прикрепляет куки bank.com
к этому запросу. Сервер bank.com
получает запрос, проверяет, что куки действительны, и затем выполняет эту несанкционированную операцию перевода.
Общие методы предотвращения атак CSRF
Вот несколько часто используемых методов защиты от CSRF. Мы объясним подробно принцип каждого метода и как он эффективно предотвращает атаки CSRF:
Использование CSRF-токенов
CSRF-токены – это один из самых популярных и эффективных методов защиты от CSRF-атак. Вот как это работает:
- Сервер генерирует уникальный, непредсказуемый токен для каждой сессии.
- Этот токен встраивается во все формы для чувствительных операций.
- Когда пользователь отправляет форму, сервер проверяет действительность токена.
Поскольку CSRF-токен – это уникальное значение, связанное с сессией пользователя, и злоумышленник не может знать или угадать это значение (так как оно отличается для каждой сессии), даже если злоумышленник обманет пользователя и заставит его отправить запрос, запрос будет отклонён сервером из-за отсутствия действительного CSRF-токена.
Пример реализации:
На стороне сервера (с использованием Node.js и Express):
Во frontend JavaScript:
Проверка заголовка Referer
Заголовок Referer
содержит URL страницы, с которой был инициализирован запрос. Путём проверки заголовка Referer
сервер может определить, идёт ли запрос из легитимного источника.
Поскольку атаки CSRF обычно происходят с разных доменов, заголовок Referer
покажет доменное имя злоумышленника. Проверяя, соответствует ли Referer
ожидаемому значению, можно блокировать запросы из неизвестных источников.
Однако стоит отметить, что этот метод не является полностью надёжным, поскольку некоторые браузеры могут не отправлять заголовок Referer, а пользователи могут отключать его через настройки браузера или плагины.
Пример реализации:
Использование атрибута куки SameSite
SameSite
– это атрибут куки, используемый для контроля, отправляются ли куки с перекрёстными запросами. Он имеет три возможных значения:
Strict
: Куки отправляются только в запросах того же сайта.Lax
: Куки отправляются в запросах того же сайта и топ-уровневой навигации.None
: Куки отправляются во всех перекрёстных запросах (должн ы использоваться с атрибутомSecure
).
При установке SameSite
на Strict
, это может полностью предотвратить отправку куки с третьих сайтов, эффективно предотвращая атаки CSRF.
Если SameSite
установлен на Lax
, это защищает чувствительные операции, одновременно допуская некоторые общие случаи перекрестного использования сайтов (например, вход на сайт из внешней ссылки).
Пример реализации:
Использование настраиваемых заголовков запросов
Для AJAX-запросов можно добавлять настраиваемые заголовки запросов. Из-за ограничений политики того же происхождения злоумышленники не могут устанавливать настраиваемые заголовки в перекрёстных запросах. Сервер может проверять наличие этого настраиваемого заголовка, чтобы проверить легитимность запроса.
Пример реализации:
На стороне клиента:
На стороне сервера: