Перейти к содержанию

Защита от межсайтовой подделки запросов (CSRF)

Razor Pages защищает от подобного рода атак по умолчанию, однако мы можем соответствующие проверки отключить. Разберем, к чему это приведёт.

Классический пример такой атаки — банковский перевод. Пусть у нас есть банковское приложение, которое хранит токены аутентификации в файлах cookie. Браузеры автоматически отправляют файлы cookie, ассоциированные с доменом, с каждым запросом.
Теперь пусть у нас есть страница, которая позволяет пользователю переводить средства со своего счёта с помощью POST-запроса. Мы выполняем вход, чтобы получить доступ к форме (страница защищена с помощью [Authorize]), после чего отправляем форму, используя POST-запрос, с указанием суммы перевода и целевого счёта.
Предположим, пользователь заходит на сайт и совершает транзакцию. После этого он заходит на другой сайт, контролируемый злоумышленником. Злоумышленник встроил форму в свой сайт, выполняющий POST-запрос к сайту нашего банка, идентичный запросу с нашего сайта, чтобы перевести средства. Браузеры автоматически отправляют файлы cookie, когда страница выполняет POST-запрос, и банковское приложение не знает, что это злонамеренный запрос!
Уязвимость в том, что браузеры автоматически отправляют файлы cookie при запросе страницы или отправке формы; это поведение позволяет пользоваться сайтами после того, как мы выполнили вход.

Распространённым решением является шаблон Синхронизирующий токен1. В этом случае используются уникальные токены, чтобы обеспечить отличие между легитимным POST-запросом и запросом от злоумышленника. Один токен хранится в cookie, а другой добавляется в форму, которую мы хотим защитить. Приложение генерирует токены во время выполнения на основе текущего пользователя, выполнившего вход, поэтому злоумышленник не сможет создать такой токен для поддельной формы.
Когда страница Razor получает POST-запрос, она срванивает значение в форме со значением в cookie. Если значения не совпадают, или какое-либо отсутствует, запрос отклоняется.

По умолчанию Razor Pages защищает нас от атак такого рода. Тег-хелпер формы автоматически устанавливает файл cookie токена противодействия подделке и добавляет его в скрытое поле __RequestVerificationToken для каждого элемента <form> в приложении.
Например, простой шаблон Razor

<form method="post">
    <label>Amount</label>
    <input type="number" name="amount" />
    <button type="submit">Withdraw funds</button>
</form>

При отрисовке в HTML он дополнится скрытым полем с токеном противодействия подделке:
<form method="post">
    <label>Amount</label>
    <input type="number" name="amount" />
    <button type="submit">Withdraw funds</button>
    <input name="__RequestVerificationToken" type="hidden" value="
OWY4NmQwODE4ODRjN2Q2NTlhMmZlYW" />
</form>

ASP.NET Core автоматически добавляет эти токены в каждую форму в Razor Pages и проверяет их. Фреймворк гарантирует, что токены есть и в cookie, и в данных формы, гарантирует их совпадение и отклоняет любые запросы в случае, если они не совпадают.

Если вместо Razor Pages используются контроллеры MVC с представлениями, ASP.NET Core по прежнему добавляет токены противодействия подделке в каждую форму, но НЕ ПРОВЕРЯЕТ их. Вместо этого необходимо декорировать контроллеры и действия атрибутами [ValidateAntiForgeryToken].

Предупреждение

ASP.NET Core не проверяет токены противодействия подделке автоматически в случае использования контроллеров MVC с представлениями. Все уязвимые методы должны быть помечены атрибутами [ValidateAntiForgeryToken], как описано в разделе “Предотвращение атак XSRF / CSRF” документации по ASP.NET Core. Если используются контроллеры веб-API, но не используются cookie для аутентификации, то уязвимость CSRF не опасна.

Если по какой-то причине необходимо явно игнорировать эти токены на странице Razor, отключить проверку можно, применив атрибут [IgnoreAntiforgeryToken] к PageModel страницы Razor.

В случае, когда данные отправляются в API не в виде формы, а в виде JSON, токен верификации необходимо отправлять в заголовке запроса2.

Создание уникальных токенов с API для защиты данных

Защитные токены обычно зависят от возможности использовать сильное симметричное шифрование.
В ASP.NET Core шифрование выполняют API защиты данных (data protection API). Они создают защитные токены, шифруют cookie-файлы и генерируют безопасные токены. Также они контролируют управления файлами ключей.
Файл ключа — это небольшой XML-файл, содержащий случайное значение ключа шифрования. Очень важно хранить его в надёжном месте.

Система защиты хранит ключи в надёжных местах (в зависимости от того, как и где размещено приложение):

  • веб-приложение Azure — в специальной сихронизированной папке;
  • IIS без профиля пользователя — зашифрованы в реестре;
  • учётная запись с профилем пользователя — в %LOCALAPPDATA%\ASP.NET\DataProtection-Keys в Windows и ~/.aspnet/DataProtection-Keys в Linux и macOS;
  • в остальных случаях — в памяти; при перезапуске приложения ключи будут потеряны.

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


  1. В статье Шпаргалка по предотвращению CSRF подробно разбирается уязвимость CSRF и шаблоны противодействия, включая Синхронизирующий токен

  2. Как конкретно это делать — зависит от использованного JavaScript-фреймворка. Примеры в документации от Microsoft даны для JQuery и AngularJS, но должна быть такая возможность и выбранном феймворке. 


Последнее обновление : 8 мая 2023 г.
Дата создания : 24 октября 2022 г.

Комментарии

Комментарии