Безопасность в Django
В данном документе представлен обзор функций безопасности Django. Он включает рекомендации по обеспечению безопасности сайта, работающего на Django.
Защита от межсайтового скриптинга (XSS)
Атаки XSS позволяют пользователю внедрять скрипты на стороне клиента в браузеры других пользователей. Обычно это достигается путем хранения вредоносных скриптов в базе данных, где они будут извлекаться и отображаться другим пользователям, или путем побуждения пользователей к переходу по ссылке, которая приведет к выполнению JavaScript-кода злоумышленника в браузере пользователя. Однако атаки XSS могут исходить из любого ненадежного источника данных, такого как куки или веб-службы, когда данные не должным образом очищаются перед включением в страницу.
Использование шаблонов Django защищает вас от большинства атак XSS. Однако важно понимать, какую защиту они обеспечивают и каковы их ограничения.
Шаблоны Django экранируют определенные символы, которые особенно опасны для HTML. Хотя это защищает пользователей от большинства вредоносных данных, это не полностью безопасно. Например, это не защищает от следующего:
<style class={{ var }}>...</style>
Если var установлено на 'class1 onmouseover=javascript:func()', это может привести к несанкционированному выполнению JavaScript в зависимости от того, как браузер отображает неполноценный HTML. (Процитирование значения атрибута решит эту проблему.)
Также важно проявлять особую осторожность при использовании is_safe с пользовательскими тегами шаблонов, тегом шаблона safe, mark_safe и при отключенном автоэкранировании.
Кроме того, если вы используете систему шаблонов для вывода чего-то, помимо HTML, могут потребоваться отдельные символы и слова, которые необходимо экранировать.
Также следует проявлять осторожность при хранении HTML в базе данных, особенно при извлечении и отображении этого HTML.
Защита от межсайтовых поддельных запросов (CSRF)
Атаки CSRF позволяют злоумышленнику выполнять действия от имени другого пользователя без его ведома или согласия.
Django имеет встроенную защиту от большинства типов атак CSRF при условии, что вы включили и использовали её при необходимости. Однако, как и в случае любой техники смягчения, существуют ограничения. Например, модуль CSRF можно отключить глобально или для определенных представлений. Делать это следует только в том случае, если вы знаете, что делаете. Существуют другие ограничения, если ваш сайт имеет поддомены, которые вы не контролируете.
Защита от CSRF работает путем проверки секретного значения в каждом запросе POST. Это гарантирует, что злоумышленник не сможет "повторно выполнить" отправку формы POST на ваш сайт и незаметно для другого авторизованного пользователя отправить эту форму. Злоумышленнику пришлось бы знать секрет, который является специфичным для пользователя (используя куки).
При развертывании с использованием HTTPS, CsrfViewMiddleware будет проверять, что заголовок HTTP referer установлен на URL того же домена (включая поддомен и порт). Поскольку HTTPS обеспечивает дополнительную безопасность, крайне важно гарантировать, что соединения используют HTTPS там, где это возможно, перенаправляя запросы небезопасных соединений и используя HSTS для поддерживаемых браузеров.
Будьте очень осторожны при применении декоратора csrf_exempt к представлениям, если это не абсолютно необходимо.
Защита от SQL-инъекций
SQL-инъекция – это тип атаки, при котором злоумышленник может выполнить произвольный SQL-код в базе данных. Это может привести к удалению записей или утечке данных.
Django querysets защищены от SQL-инъекций, так как их запросы строятся с использованием параметризации запросов. SQL-код запроса определяется отдельно от параметров запроса. Поскольку параметры могут быть предоставлены пользователем и, следовательно, небезопасны, они экранируются базовым драйвером базы данных.
Django также предоставляет разработчикам возможность писать необработанные запросы или выполнять пользовательский SQL. Эти возможности следует использовать с осторожностью, и всегда необходимо внимательно экранировать любые параметры, на которые пользователь может повлиять. Кроме того, следует проявлять осторожность при использовании extra() и RawSQL.
Защита от Clickjacking
Clickjacking – это тип атаки, при которой вредоносный сайт заключает целевой сайт в фрейм. Эта атака может привести к тому, что неосторожный пользователь будет обманут на выполнение нежелательных действий на целевом сайте.
Django содержит защиту от clickjacking в виде X-Frame-Options middleware, которая в поддерживающем браузере может предотвратить отображение сайта внутри фрейма. Защиту можно отключить для отдельных представлений или настроить точное значение отправляемого заголовка.
Средство промежуточного программного обеспечения настоятельно рекомендуется для любого сайта, которому не нужно отображать страницы внутри фрейма со стороны сторонних сайтов или который требует этого только для небольшой части сайта.
SSL/HTTPS
Для обеспечения безопасности рекомендуется развертывать сайт через HTTPS. Без этого злоумышленники в сети могут перехватывать учетные данные аутентификации или любую другую информацию, передаваемую между клиентом и сервером, а в некоторых случаях – активные злоумышленники в сети – могут изменять данные, отправляемые в любом направлении.
Если вы хотите воспользоваться преимуществами защиты HTTPS и включили его на сервере, вам могут потребоваться дополнительные шаги:
- При необходимости задайте
SECURE_PROXY_SSL_HEADER, убедившись, что вы полностью поняли предупреждения там. Невыполнение этого может привести к уязвимостям CSRF, а неправильное выполнение также может быть небезопасно! -
Установите
SECURE_SSL_REDIRECTнаTrue, чтобы запросы по протоколу HTTP перенаправлялись на HTTPS.Обратите внимание на замечания в разделе
SECURE_PROXY_SSL_HEADER. В случае обратного прокси-сервера может быть проще или безопаснее настроить основной веб-сервер для перенаправления на HTTPS. -
Используйте «безопасные» куки.
Если браузер изначально подключается по протоколу HTTP, что является стандартным для большинства браузеров, существующие куки могут быть раскрыты. По этой причине вы должны установить значения
SESSION_COOKIE_SECUREиCSRF_COOKIE_SECUREнаTrue. Это указывает браузеру отправлять эти куки только по HTTPS-соединениям. Обратите внимание, что это означает, что сеансы не будут работать по HTTP, а защита от CSRF предотвратит прием любых данных POST по HTTP (что будет нормально, если вы перенаправляете весь трафик HTTP на HTTPS). -
Используйте HTTP Strict Transport Security (HSTS)
HSTS – это заголовок HTTP, который сообщает браузеру, что все будущие соединения с данным сайтом всегда должны использовать HTTPS. В сочетании с перенаправлением запросов по протоколу HTTP на HTTPS это гарантирует, что соединения всегда будут пользоваться дополнительной безопасностью SSL при условии успешного установления одного соединения. HSTS можно настроить с помощью
SECURE_HSTS_SECONDS,SECURE_HSTS_INCLUDE_SUBDOMAINSиSECURE_HSTS_PRELOAD, или на веб-сервере.
Проверка заголовка Host
Django использует заголовок Host, предоставленный клиентом, для построения URL-адресов в некоторых случаях. Хотя эти значения очищаются для предотвращения атак типа Cross-Site Scripting, поддельный заголовок Host может использоваться для атак типа Cross-Site Request Forgery, отравления кэша и подмены ссылок в электронных письмах.
Поскольку даже, казалось бы, защищённые конфигурации веб-сервера уязвимы к поддельным заголовкам Host, Django проверяет заголовки Host по отношению к настройке ALLOWED_HOSTS в методе django.http.HttpRequest.get_host().
Эта проверка применяется только через get_host(); если ваш код обращается к заголовку Host напрямую из request.META, вы обходите эту защитную меру.
Дополнительную информацию см. в полной документации к ALLOWED_HOSTS.
Предупреждение
Предыдущие версии этого документа рекомендовали настроить ваш веб-сервер таким образом, чтобы он проверял входящие HTTP-заголовки Host. Хотя это всё ещё рекомендуется, во многих распространённых веб-серверах конфигурация, которая, кажется, проверяет заголовок Host, на самом деле этого не делает. Например, даже если Apache настроен так, что ваш сайт Django обслуживается с виртуального хоста по умолчанию с установленным ServerName, всё ещё возможно, что HTTP-запрос будет соответствовать этому виртуальному хосту и передавать поддельный заголовок Host. Таким образом, Django теперь требует, чтобы вы явно установили ALLOWED_HOSTS, а не полагались на конфигурацию веб-сервера.
Кроме того, Django требует явно включить поддержку заголовка X-Forwarded-Host (через настройку USE_X_FORWARDED_HOST), если ваша конфигурация этого требует.
Политика переадресации
Браузеры используют заголовок Referer в качестве способа отправки информации на сайт о том, как пользователи на него попали. Установив политику переадресации, вы можете помочь защитить конфиденциальность своих пользователей, ограничив обстоятельства, при которых устанавливается заголовок Referer. Подробности см. в разделе политики переадресации в справке по middleware безопасности.
Политика открытия перекрёстного происхождения
Заголовок политики открытия перекрёстного происхождения (COOP) позволяет браузерам изолировать окно верхнего уровня от других документов, поместив их в разные группы контекстов, чтобы они не могли напрямую взаимодействовать с окном верхнего уровня. Если документ, защищённый COOP, открывает окно всплывающего окна перекрёстного происхождения, свойство window.opener всплывающего окна будет null. COOP защищает от атак перекрёстного происхождения. Подробности см. в разделе политики открытия перекрёстного происхождения в справке по middleware безопасности.
Безопасность сеансов
Аналогично ограничениям CSRF, требующим развертывания сайта таким образом, чтобы неуполномоченные пользователи не имели доступа к поддоменам, django.contrib.sessions также имеет ограничения. Подробности см. в разделе руководства по сессиям о безопасности.
Безопасность загружаемого пользователем контента
Примечание
Рассмотрите обслуживание статических файлов из облачного сервиса или CDN, чтобы избежать некоторых из этих проблем.
- Если ваш сайт принимает загрузку файлов, настоятельно рекомендуется ограничить эти загрузки на сервере разумным размером, чтобы предотвратить атаки типа «отказ в обслуживании» (DOS). В Apache это можно легко установить, используя директиву LimitRequestBody.
- Если вы сами обслуживаете статические файлы, убедитесь, что обработчики, такие как
mod_phpApache, которые выполняли бы статические файлы как код, отключены. Вы не хотите, чтобы пользователи могли выполнять произвольный код, загружая и запрашивая специально созданный файл. -
Обработка загрузки изображений Django имеет некоторые уязвимости, когда эти изображения обслуживаются способами, которые не следуют лучшим практикам безопасности. В частности, HTML-файл может быть загружен как изображение, если этот файл содержит допустимый заголовок PNG, за которым следует вредоносный HTML. Этот файл пройдёт проверку библиотеки, которую Django использует для обработки изображений
ImageField(Pillow). Когда этот файл впоследствии отображается пользователю, он может отображаться как HTML в зависимости от типа и конфигурации вашего веб-сервера.В рамках фреймворка не существует технического решения, гарантирующего безопасную проверку всего загружаемого пользователем контента; однако есть несколько других шагов, которые вы можете предпринять для смягчения этих атак:
- Один класс атак можно предотвратить, всегда обслуживая загружаемый пользователем контент с отдельного домена верхнего или второго уровня. Это предотвращает любые эксплойты, блокируемые политикой одинакового происхождения, такие как атаки типа «межсайтовый скриптинг». Например, если ваш сайт работает на
example.com, вы хотели бы обслуживать загружаемый контент (настройкаMEDIA_URL) с помощью чего-то вродеusercontent-example.com. Недостаточно просто обслуживать контент с поддомена, например,usercontent.example.com. - Помимо этого, приложения могут выбрать определение списка разрешённых расширений файлов для загружаемых пользователем файлов и настроить веб-сервер на обслуживание только таких файлов.
- Один класс атак можно предотвратить, всегда обслуживая загружаемый пользователем контент с отдельного домена верхнего или второго уровня. Это предотвращает любые эксплойты, блокируемые политикой одинакового происхождения, такие как атаки типа «межсайтовый скриптинг». Например, если ваш сайт работает на
Дополнительные темы безопасности
Хотя Django предоставляет хорошую защиту по умолчанию, всё равно важно правильно развернуть своё приложение и использовать средства защиты веб-сервера, операционной системы и других компонентов.
- Убедитесь, что ваш Python-код находится вне корня веб-сервера. Это гарантирует, что ваш Python-код не будет случайно обслуживаться как простой текст (или случайно выполняться).
- Обращайте внимание на любые загружаемые пользователем файлы.
- Django не ограничивает количество запросов для аутентификации пользователей. Для защиты от атак типа «грубой силы» на систему аутентификации вы можете рассмотреть возможность развертывания плагина Django или модуля веб-сервера для ограничения этих запросов.
- Сохраняйте
SECRET_KEYиSECRET_KEY_FALLBACKS, если они используются, в секрете. - Рекомендуется ограничивать доступ к вашей системе кэширования и базе данных с помощью брандмауэра.
- Обратите внимание на список 10 наиболее распространённых уязвимостей веб-приложений Open Web Application Security Project (OWASP) здесь. Хотя Django имеет инструменты для решения некоторых проблем, другие проблемы должны быть учтены при проектировании вашего проекта.
- Mozilla обсуждает различные темы, связанные с безопасностью веб-приложений. Их страницы также содержат принципы безопасности, применимые к любой системе.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/5.2/topics/security/