Безопасность в 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 защищены от 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. -
Используйте «безопасные» cookie.
Если браузер первоначально подключается по 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-адресов в некоторых случаях. Хотя эти значения очищаются для предотвращения атак межсайтовых сценариев (XSS), поддельный заголовок Host может использоваться для атак межсайтовых поддельных запросов (CSRF), отравления кэша и отравления ссылок в электронных письмах.
Поскольку даже, казалось бы, безопасные конфигурации веб-серверов уязвимы к поддельным заголовкам 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 . Подробнее см. в разделе политики реферера в справке по обработке безопасности.
Политика открытия кросс-доменных окон
Заголовок политики открытия кросс-доменных окон (COOP) позволяет браузерам изолировать окно верхнего уровня от других документов, помещая их в разные группы контекстов, чтобы они не могли напрямую взаимодействовать с окном верхнего уровня. Если документ, защищённый политикой COOP, открывает всплывающее окно из другого домена, свойство window.opener всплывающего окна будет null. COOP защищает от атак через кросс-доменные окна. Подробнее см. в разделе политики открытия кросс-доменных окон в справке по обработке безопасности.
Безопасность сессий
Аналогично ограничениям CSRF, требующим, чтобы сайт был развернут таким образом, чтобы неуполномоченные пользователи не имели доступа к каким-либо поддоменам, django.contrib.sessions также имеет ограничения. Подробнее см. раздел руководства по темам сессий о безопасности.
Безопасность пользовательского контента
Примечание
Рассмотрите возможность обслуживания статических файлов с облачного сервиса или CDN, чтобы избежать некоторых из этих проблем.
- Если ваш сайт принимает загрузки файлов, настоятельно рекомендуется ограничить эти загрузки разумным размером в конфигурации веб-сервера, чтобы предотвратить атаки типа «отказ в обслуживании» (DOS). В Apache это можно легко установить с помощью директивы LimitRequestBody.
- Если вы обслуживаете свои собственные статические файлы, убедитесь, что обработчики, такие как
mod_php, которые выполняли бы статические файлы как код, отключены. Вы не хотите, чтобы пользователи могли выполнить произвольный код, загрузив и запросив специально подготовленный файл. -
Обработка загрузок медиа-файлов 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(если используются) в секрете. - Хорошей идеей является ограничение доступа к вашей системе кэширования и базе данных с помощью брандмауэра.
- Посмотрите на список десяти наиболее распространенных уязвимостей веб-приложений Open Web Application Security Project (OWASP) Top 10. Хотя Django имеет инструменты для решения некоторых проблем, другие проблемы необходимо учитывать при проектировании вашего проекта.
- Mozilla обсуждает различные темы, касающиеся безопасности веб-приложений. Их страницы также включают принципы безопасности, применимые к любой системе.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/4.2/topics/security/