Spec-Zone.ru › Django 4.2

Защита от межсайтовых поддельных запросов

Средство промежуточного ПО CSRF и тег шаблона обеспечивают простую в использовании защиту от межсайтовых поддельных запросов. Этот тип атаки происходит, когда вредоносный веб-сайт содержит ссылку, кнопку формы или какой-либо JavaScript-код, предназначенный для выполнения действия на вашем веб-сайте с использованием учетных данных вошедшего в систему пользователя, который посещает вредоносный сайт в своем браузере. Также рассматривается связанный тип атаки, «CSRF-атака на вход», когда атакующий сайт обманывает браузер пользователя, чтобы он вошел в систему на сайте с учетными данными другого человека.

Первой защитой от атак CSRF является обеспечение того, чтобы запросы GET (и другие «безопасные» методы, как определено в RFC 9110#section-9.2.1) не имели побочных эффектов. Запросы с использованием «опасных» методов, таких как POST, PUT и DELETE, могут затем быть защищены шагами, описанными в Как использовать защиту от CSRF Django.

Как это работает

Защита от CSRF основана на следующих моментах:

  1. Файл cookie CSRF, содержащий случайное секретное значение, к которому другие сайты не имеют доступа.

    CsrfViewMiddleware отправляет этот cookie вместе с ответом всякий раз, когда django.middleware.csrf.get_token() вызывается. Он также может отправлять его и в других случаях. По соображениям безопасности значение секрета меняется каждый раз, когда пользователь входит в систему.

  2. Скрытое поле формы с именем «csrfmiddlewaretoken», присутствующее во всех исходящих формах POST.

    Для защиты от атак BREACH значение этого поля не является просто секретом. Оно зашифровывается по-разному с каждым ответом с использованием маски. Маска генерируется случайным образом при каждом вызове get_token(), поэтому значение поля формы отличается каждый раз.

    Эта часть выполняется тегом шаблона.

  3. Для всех входящих запросов, которые не используют HTTP GET, HEAD, OPTIONS или TRACE, должен быть представлен файл cookie CSRF, а поле «csrfmiddlewaretoken» должно быть представлено и корректным. Если это не так, пользователю будет возвращена ошибка 403.

    При проверке значения поля «csrfmiddlewaretoken» сравнивается только секрет, а не весь токен, с секретом в значении cookie. Это позволяет использовать постоянно изменяющиеся токены. Хотя каждый запрос может использовать свой собственный токен, секрет остается общим для всех.

    Эта проверка выполняется CsrfViewMiddleware.

  4. CsrfViewMiddleware проверяет заголовок Origin, если он предоставлен браузером, относительно текущего хоста и параметра CSRF_TRUSTED_ORIGINS. Это обеспечивает защиту от атак между поддоменами.
  5. Кроме того, для запросов HTTPS, если заголовок Origin не предоставлен, CsrfViewMiddleware выполняет строгую проверку referer. Это означает, что даже если поддомен может устанавливать или изменять файлы cookie на вашем домене, он не может заставить пользователя отправить POST-запрос на ваше приложение, так как этот запрос не будет исходить с вашего точного домена.

    Это также устраняет атаку «человек посередине», которая возможна при использовании HTTPS с независимым от сессии секретом, поскольку заголовки HTTP Set-Cookie (к сожалению) принимаются клиентами даже при общении с сайтом по протоколу HTTPS. (Проверка referer не выполняется для HTTP-запросов, поскольку наличие заголовка Referer недостаточно надежно в HTTP-среде.)

    Если параметр CSRF_COOKIE_DOMAIN задан, referer сравнивается с ним. Вы можете разрешить запросы между поддоменами, включив ведущую точку. Например, CSRF_COOKIE_DOMAIN = '.example.com' позволит запросы POST из www.example.com и api.example.com. Если параметр не задан, referer должен совпадать с заголовком HTTP Host.

    Расширение допустимых referer за пределы текущего хоста или домена cookie можно выполнить с помощью параметра CSRF_TRUSTED_ORIGINS.

Изменено в Django 4.1:

В более ранних версиях значение cookie CSRF маскировалось.

Это гарантирует, что формы, которые исходят из доверенных доменов, могут использоваться для отправки данных POST обратно.

Это преднамеренно игнорирует запросы GET (и другие запросы, определенные как «безопасные» в RFC 9110#section-9.2.1). Эти запросы никогда не должны иметь потенциально опасных побочных эффектов, и поэтому атака CSRF с запросом GET должна быть безопасной. RFC 9110#section-9.2.1 определяет POST, PUT и DELETE как «опасные», а все другие методы также предполагаются опасными для максимальной защиты.

Защита от CSRF не защищает от атак «человек посередине», поэтому используйте HTTPS вместе с HTTP Strict Transport Security. Она также предполагает проверку заголовка HOST и отсутствие уязвимостей межсайтового скриптинга на вашем сайте (так как уязвимости XSS уже позволяют злоумышленнику делать все, что позволяет уязвимость CSRF, и даже больше).

Удаление заголовка Referer

Чтобы избежать раскрытия URL-адреса referer сторонним сайтам, вы можете отключить referer на тегах <a> вашего сайта. Например, вы можете использовать тег <meta name="referrer" content="no-referrer"> или включить заголовок Referrer-Policy: no-referrer. Из-за строгой проверки referer в защите от CSRF при запросах HTTPS эти методы приведут к ошибке CSRF при запросах с «опасными» методами. Вместо этого используйте альтернативы, такие как <a rel="noreferrer" ...>" для ссылок на сторонние сайты.

Ограничения

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

Утилиты

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

csrf_exempt(view)

Этот декоратор отмечает представление как освобождённое от защиты, обеспечиваемой средством промежуточного ПО. Пример:

from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt


@csrf_exempt
def my_view(request):
    return HttpResponse("Hello world")
csrf_protect(view)

Декоратор, обеспечивающий защиту CsrfViewMiddleware для представления.

Использование:

from django.shortcuts import render
from django.views.decorators.csrf import csrf_protect


@csrf_protect
def my_view(request):
    c = {}
    # ...
    return render(request, "a_template.html", c)
requires_csrf_token(view)

Обычно тег шаблона csrf_token не будет работать, если CsrfViewMiddleware.process_view или эквивалент, например csrf_protect, не был выполнен. Декоратор представления requires_csrf_token может использоваться для обеспечения работы тега шаблона. Этот декоратор работает аналогично csrf_protect, но никогда не отклоняет входящий запрос.

Пример:

from django.shortcuts import render
from django.views.decorators.csrf import requires_csrf_token


@requires_csrf_token
def my_view(request):
    c = {}
    # ...
    return render(request, "a_template.html", c)
ensure_csrf_cookie(view)

Этот декоратор принуждает представление к отправке файла cookie CSRF.

Настройки

Ряд настроек может использоваться для управления поведением CSRF Django:

  • CSRF_COOKIE_AGE
  • CSRF_COOKIE_DOMAIN
  • CSRF_COOKIE_HTTPONLY
  • CSRF_COOKIE_NAME
  • CSRF_COOKIE_PATH
  • CSRF_COOKIE_SAMESITE
  • CSRF_COOKIE_SECURE
  • CSRF_FAILURE_VIEW
  • CSRF_HEADER_NAME
  • CSRF_TRUSTED_ORIGINS
  • CSRF_USE_SESSIONS

Часто задаваемые вопросы

Является ли отправка произвольной пары токенов CSRF (cookie и данные POST) уязвимостью?

Нет, это сделано по умолчанию. Без атаки «человек посередине» злоумышленник не может отправить файл cookie CSRF в браузер жертвы, поэтому успешная атака потребует получения cookie браузера жертвы через XSS или аналогичное действие, в этом случае злоумышленнику обычно не нужны атаки CSRF.

Некоторые инструменты аудита безопасности отмечают это как проблему, но, как упоминалось ранее, злоумышленник не может украсть файл cookie CSRF браузера пользователя. «Кража» или изменение вашего собственного токена с помощью Firebug, инструментов разработчика Chrome и т. д. не является уязвимостью.

Является ли проблемой то, что защита от CSRF Django по умолчанию не связана с сеансом?

Нет, это сделано по умолчанию. Отключение привязки защиты CSRF к сеансу позволяет использовать защиту на сайтах, таких как pastebin, которые позволяют отправлять данные анонимным пользователям, у которых нет сеанса.

Если вы хотите сохранить маркер CSRF в сеансе пользователя, используйте настройку CSRF_USE_SESSIONS.

Почему пользователь может столкнуться с ошибкой валидации CSRF после входа в систему?

По соображениям безопасности маркеры CSRF обновляются каждый раз при входе пользователя в систему. Любая страница с формой, сгенерированной до входа в систему, будет содержать старый, недействительный маркер CSRF и потребует перезагрузки. Это может произойти, если пользователь использует кнопку «Назад» после входа в систему или если он входит в систему в другой вкладке браузера.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/4.2/ref/csrf/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API