Защита от межсайтовых поддельных запросов
Средства обработки CSRF и тег шаблона предоставляют простую в использовании защиту от межсайтовых поддельных запросов. Этот тип атаки происходит, когда вредоносный веб-сайт содержит ссылку, кнопку формы или какой-либо JavaScript, предназначенные для выполнения какого-либо действия на вашем веб-сайте, используя учетные данные вошедшего в систему пользователя, который посещает вредоносный сайт в своём браузере. Также рассматривается связанный тип атаки — «CSRF входа», когда атакующий сайт обманывает браузер пользователя, заставляя его войти на сайт с чужими учетными данными.
Первой защитой от атак CSRF является обеспечение того, чтобы запросы GET (и другие «безопасные» методы, как определено в RFC 7231#section-4.2.1) были лишены побочных эффектов. Запросы с помощью «небезопасных» методов, таких как POST, PUT и DELETE, могут быть защищены шагами, описанными в Как использовать защиту Django от CSRF.
Как это работает
Защита от CSRF основана на следующем:
-
Файл cookie CSRF, содержащий случайное секретное значение, к которому другие сайты не имеют доступа.
CsrfViewMiddlewareотправляет этот файл cookie вместе с ответом всякий раз, когдаdjango.middleware.csrf.get_token()вызывается. Он также может отправлять его в других случаях. По соображениям безопасности значение секрета изменяется каждый раз, когда пользователь входит в систему. -
Скрытое поле формы с именем «csrfmiddlewaretoken», присутствующее во всех исходящих формах POST.
Чтобы защититься от атак BREACH, значение этого поля не является просто секретом. Оно шифруется по-разному в каждом ответе с помощью маски. Маска генерируется случайным образом при каждом вызове
get_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.
Origin проверка была добавлена, как описано выше.
В более старых версиях значение файла cookie CSRF маскировалось.
Это гарантирует, что формы, которые были получены с доверенных доменов, могут использоваться для отправки данных POST.
Она преднамеренно игнорирует запросы GET (и другие запросы, определённые как «безопасные» в RFC 7231#section-4.2.1). Эти запросы никогда не должны иметь каких-либо потенциально опасных побочных эффектов, поэтому атака CSRF с запросом GET должна быть безвредной. RFC 7231#section-4.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) -
Этот декоратор отмечает представление как освобожденное от защиты, обеспеченной средствами обработки.
Пример:
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.
Настройки
Несколько настроек могут использоваться для управления поведением Django CSRF:
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) уязвимостью?
Нет, это сделано по умолчанию. Без атаки «человек посередине» злоумышленник не может отправить файл cookie CSRF в браузер жертвы, поэтому успешная атака должна получить файл cookie браузера жертвы через XSS или подобное, в этом случае злоумышленнику обычно не нужны атаки CSRF.
END_OF_DOCUMENT_MARKERНекоторые инструменты аудита безопасности отмечают это как проблему, но, как уже упоминалось ранее, злоумышленник не может украсть куки CSRF браузера пользователя. «Кража» или изменение вашего собственного токена с помощью Firebug, инструментов разработчика Chrome и т. д. не является уязвимостью.
Является ли проблемой то, что защита Django CSRF по умолчанию не связана с сессией?
Нет, это сделано по умолчанию. Отсутствие связи защиты 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.1/ref/csrf/