Защита от межсайтовых поддельных запросов
Модуль промежуточного программного обеспечения CSRF и тег шаблона предоставляют простую в использовании защиту от межсайтовых поддельных запросов. Этот тип атаки происходит, когда вредоносный веб-сайт содержит ссылку, кнопку формы или какой-либо JavaScript, предназначенный для выполнения некоторого действия на вашем веб-сайте, используя учетные данные вошедшего в систему пользователя, который посещает вредоносный сайт в своем браузере. Также рассматривается родственный тип атаки, «CSRF входа», где атакующий сайт обманывает браузер пользователя, заставляя его войти на сайт под чужими учетными данными.
Первой защитой от атак CSRF является обеспечение того, чтобы запросы GET (и другие «безопасные» методы, как определено в RFC 9110#section-9.2.1) не имели побочных эффектов. Запросы с помощью «опасных» методов, таких как POST, PUT и DELETE, затем можно защитить, выполнив шаги, описанные в Как использовать защиту Django от CSRF.
Как это работает
Защита от CSRF основана на следующих вещах:
-
Файл cookie CSRF, содержащий случайное секретное значение, к которому у других сайтов нет доступа.
CsrfViewMiddlewareотправляет этот файл cookie с ответом всякий раз, когдаdjango.middleware.csrf.get_token()вызывается. Он также может отправлять его и в других случаях. По соображениям безопасности значение секрета изменяется каждый раз, когда пользователь входит в систему. -
Скрытое поле формы с именем ‘csrfmiddlewaretoken’, присутствующее во всех исходящих формах POST.
Чтобы защититься от атак BREACH, значение этого поля не просто секрет. Оно зашифровывается по-разному с каждым ответом с использованием маски. Маска генерируется случайным образом при каждом вызове
get_token(), поэтому значение поля формы каждый раз отличается.Эта часть выполняется тегом шаблона
csrf_token. -
Для всех входящих запросов, которые не используют HTTP GET, HEAD, OPTIONS или TRACE, должен быть присутствующим и корректным файл cookie CSRF и поле ‘csrfmiddlewaretoken’. Если это не так, пользователь получит ошибку 403.
При проверке значения поля ‘csrfmiddlewaretoken’ сравнивается только секрет, а не весь токен, со значением секрета в файле cookie. Это позволяет использовать постоянно меняющиеся токены. Хотя каждый запрос может использовать свой собственный токен, секрет остается общим для всех.
Эта проверка выполняется
CsrfViewMiddleware. -
CsrfViewMiddlewareпроверяет заголовок Origin, если он предоставлен браузером, относительно текущего хоста и настройкиCSRF_TRUSTED_ORIGINS. Это обеспечивает защиту от междоменных атак. -
Кроме того, для запросов HTTPS, если заголовок
Originне предоставлен,CsrfViewMiddlewareвыполняет строгую проверку referer. Это означает, что даже если домен второго уровня может устанавливать или изменять файлы cookie на вашем домене, он не может заставить пользователя отправить запрос на вашу программу, поскольку этот запрос не поступает с вашего точного домена.Это также устраняет возможность атаки «человек посередине», возможной при использовании независимого от сеанса секрета по 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 должен совпадать с заголовком HTTPHost.Расширение разрешенных referer за пределы текущего хоста или домена cookie можно сделать с помощью настройки
CSRF_TRUSTED_ORIGINS.
Это гарантирует, что формы, которые возникли на доверенных доменах, могут использоваться для отправки данных 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 на вашем сайте (потому что уязвимости 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)[source] -
Этот декоратор помечает представление как освобождённое от защиты, обеспечиваемой модулем промежуточного программного обеспечения. Пример:
from django.http import HttpResponse from django.views.decorators.csrf import csrf_exempt @csrf_exempt def my_view(request): return HttpResponse("Hello world")Изменено в Django 5.0:Добавлена поддержка обертывания асинхронных функций представлений.
-
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)Изменено в Django 5.0:Добавлена поддержка обертывания асинхронных функций представлений.
-
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)Изменено в Django 5.0:Добавлена поддержка обертывания асинхронных функций представлений.
-
ensure_csrf_cookie(view) -
Этот декоратор принуждает представление отправлять файл cookie CSRF.
Изменено в Django 5.0:Добавлена поддержка обертывания асинхронных функций представлений.
Настройки
Несколько настроек могут использоваться для управления поведением CSRF Django:
CSRF_COOKIE_AGECSRF_COOKIE_DOMAINCSRF_COOKIE_HTTPONLYCSRF_COOKIE_NAMECSRF_COOKIE_PATHCSRF_COOKIE_SAMESITECSRF_COOKIE_SECURECSRF_FAILURE_VIEWCSRF_HEADER_NAMECSRF_TRUSTED_ORIGINSCSRF_USE_SESSIONS
Часто задаваемые вопросы
Является ли отправка произвольной пары токенов CSRF (файл cookie и данные POST) уязвимостью?
Нет, это сделано по умолчанию. Без атаки «человек посередине» злоумышленник не может отправить куки-файл CSRF-токен в браузер жертвы, поэтому для успешной атаки необходимо получить куки браузера жертвы с помощью XSS или аналогичных методов. В этом случае злоумышленнику обычно не нужны атаки CSRF.
Некоторые инструменты аудита безопасности отмечают это как проблему, но, как уже говорилось, злоумышленник не может украсть куки 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/5.1/ref/csrf/