• 3.1
  • 3.2
  • 5.0
  • Версия документации: 6.1

Безопасность в Django

Этот документ рассматривает возможности Django с точки зрения безопасности. В документе приведены советы по защите сайтов, созданных с помощью Django.

Всегда дезинфицируйте вводимые пользователем данные

Золотое правило безопасности веб-приложений — никогда не доверять данным, контролируемым пользователем. Следовательно, весь пользовательский ввод должен быть очищен перед использованием в вашем приложении. Подробную информацию о проверке вводимых пользователем данных в Django см. в документации по формам </topics/forms/index>`.

Защита от межсайтового скриптинга (XSS)

XSS-атаки позволяют пользователю внедрять клиентские сценарии в браузеры других пользователей. Обычно это достигается путем хранения вредоносных сценариев в базе данных, откуда они будут извлекаться и отображаться другим пользователям, или путем предложения пользователям щелкнуть ссылку, которая приведет к выполнению JavaScript злоумышленника браузером пользователя. Однако XSS-атаки могут исходить из любого ненадежного источника данных, например файлов cookie или веб-служб, если данные не проходят достаточную очистку перед включением на страницу.

Использование шаблонов 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 на вашем веб-сайте и позволить другому вошедшему в систему пользователю невольно отправить эту форму. Злоумышленник должен будет знать секрет, специфичный для пользователя (с использованием файла cookie).

При работе через HTTPS, CsrfViewMiddleware будет проверять, что заголовок HTTP Referer установлен на URL того же источника (включая поддомен и порт). Так как HTTPS предоставляет дополнительную защиту, надо всегда проверять, что соединения используют его всегда, перенаправляя на HTTPS запросы по незащищённым соединениям и используя HSTS для браузеров, которые это поддерживают.

Будьте очень внимательны, декорируя представления с помощью csrf_exempt, когда в этом нет явной необходимости.

Защита от внедрения SQL

Внедрение SQL — это тип атаки, когда недобросовестный пользователь имеет возможность выполнить в базе данных определённый SQL запрос. Результатом выполнения такого запроса может быть удаление или даже утечка данных.

Забросы через Django ORM защищены от SQL-инъекции т.к. они формируются с использованием параметров запроса. SQL код запроса отделен от параметров запроса. Т.к. параметры запроса могут поступать от пользователя и быть не безопасными, они экранируют на уровне драйвера базы данных.

Django предоставляет разработчикам возможность писать запросы напрямую или выполнять собственные запросы. Эти возможности следует использовать умеренно и всегда обращать пристальное внимание на экранирование всех параметров, которые предоставлены пользователем. Также следует проявлять осторожность при использовании extra() и RawSQL.

Защита от скликивания

Скликивание — это атака, при которой вредоносный сайт подменяет другой сайт используя <iframe>. В результате этой атаки ничего не подозревающий пользователь принуждается к выполнению определённых действий на целевом сайте.

Django предоставляет защиту от этой атаки в виде модуля X-Frame-Options, который, при использовании соответствующего браузера, может предотвратить отображение сайта внутри фрейма. Есть возможность отключить данную защиту для выбранных представлений или настроить значение отправляемого заголовка.

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

SSL/HTTPS

Лучше предоставлять доступ к вашему сайту только через HTTPS. При отсутствии HTTPS злоумышленник имеет возможность перехватывать аутентификационные данные или любую другую информацию, передаваемую между клиентом и сервером. А в случае активной атаки — может даже изменять данные, передаваемые в любом направлении.

Если вам нужна защита, предоставляемая HTTPS, и на сервере произведена соответствующая настройка ПО, то надо выполнить ещё несколько шагов, чтобы быть уверенным в защите своей информации:

  • При необходимости, установите параметр конфигурации SECURE_PROXY_SSL_HEADER, чтобы показать, что вы поняли все предупреждения. Отказ от этого может привести к CSRF проблемам, а отказ сделать это правильно также может быть опасен!

  • Настройте перенаправление HTTP запросов на HTTPS, указав True в SECURE_SSL_REDIRECT.

    Обратите внимание на предостережения в разделе 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 или на веб-сервере.

Проверка заголовка хоста

Django использует заголовок Host, предоставляемый клиентом, для создания URL в определённых случаях. Несмотря на то, что эти данные безопасны с точки зрения Cross Site Scripting атак, поддельный заголовок Host может быть использован для атак CSRF, подмены кэша и для подмены ссылок в сообщениях электронной почты.

Поскольку даже кажущиеся безопасными конфигурации веб-сервера подвержены поддельным заголовкам Host, Django проверяет заголовки Host на соответствие настройке ALLOWED_HOSTS в методе django.http.HttpRequest.get_host().

Эта проверка применяется только через get_host(); если ваш код обращается к заголовку Host непосредственно из request.META, вы обходите эту защиту.

Для подробностей смотрите полную документацию на параметр конфигурации ALLOWED_HOSTS.

Предупреждение

Предыдущие версии этого документа рекомендовали настраивать ваш веб сервер на проверку входящих HTTP заголовков Host. Рекомендация всё ещё в силе, на многих веб-серверах используется конфигурация, которая не проверяет заголовок Host, хотя по всем признакам должна это делать. Например, даже если Apache настроен таким образом, что ваш сайт работает на нестандартном виртуальном узле с установленным ServerName, всё ещё есть возможность предоставить поддельный заголовок для этого узла. Таким образом, Django теперь требует явного определения параметра конфигурации ALLOWED_HOSTS, не доверяя конфигурации самого веб сервера.

Дополнительно Django требует явную активацию поддержки заголовка X-Forwarded-Host (через параметр конфигурации USE_X_FORWARDED_HOST), если ваша конфигурация в нём нуждается.

Политика Referrer

Браузеры используют заголовок Referer для передачи информации сайту о том, как пользователь попал на него. Устанавливая Политику Referrer вы можете помочь защитить приватность ваших пользователей, указывая при каких обстоятельствах устанавливается заголовок Referer. Обратитесь к соответствующему разделу настроек безовасности для подробностей.

Политика открытия перекрестного происхождения

Заголовок политики открытия перекрестного происхождения (COOP) позволяет браузерам изолировать окно верхнего уровня от других документов, помещая их в другую контекстную группу, чтобы они не могли напрямую взаимодействовать с окном верхнего уровня. Если документ, защищенный COOP, открывает всплывающее окно из разных источников, свойство всплывающего окна window.opener будет иметь значение null. COOP защищает от атак из разных источников. Дополнительную информацию см. в разделе политики открытия перекрестного происхождения в справочнике по промежуточному программному обеспечению безопасности <cross-origin-opener-policy>`.

Безопасность сессии

Аналогично требованиям ограничений CSRF, чтобы сайт был настроен так, чтобы недоверенные пользователи не имели доступа ни к одному поддомену, django.contrib.sessions также имеет ограничения. Обратитесь к разделу по безопасной настройке сессий для подробностей.

Контент, загружаемый пользователями

Примечание

Обратите внимание на раздачу файлов из облачного сервиса или CDN для избежания некоторых из этих проблем.

  • Если ваш сайт поддерживает загрузку файлов, настоятельно рекомендуется ограничить эту загрузку в конфигурации вашего веб-сервера разумным размером, чтобы предотвратить атаки типа «отказ в обслуживании» (DOS). В Apache это можно легко настроить с помощью директивы LimitRequestBody.

  • Если вы самостоятельно раздаете статические файлы, убедитесь, что обработчики, как mod_php в Apache, который будет выполнять статические файлы в виде кода, будут отключены. Вы же не хотите, чтобы пользователи могли выполнить произвольный код путем загрузки и запроса специально созданного файла.

  • Обработка загрузки медиа файлов в Django имеет некоторые уязвимости, если медиа файлы раздаются без учета некоторых правил безопасности. В частности, HTML файл может быть загружен в виде изображения, если этот файл содержит правильный заголовок PNG с последующим вредоносным HTML. Этот файл будет проходить проверку библиотеками, которые Django использует для обработки изображений (Pillow) в ImageField. Когда этот файл впоследствии отображается для пользователя, он может отображаться как HTML в зависимости от типа и конфигурации веб-сервера.

    Не существует идеального технического решения на уровне Django для безопасной проверки всех типов файлов, которые могут загрузить другие пользователи. Однако, можно предпринять некоторые другие способы, чтобы обезопасить себя от атаки:

    1. Один класс атак можно предотвратить путем раздачи медиа файлов с отдельного домена верхнего уровня или второго уровня. Это предотвращает любые эксплойты, которые могут быть заблокированы same-origin policy, таких как межсайтовый скриптинг. Например, если ваш сайт работает на example.com, вам следует раздавать медиа файлы (настройка MEDIA_URL) с другого домена, например usercontent-example.com. Но не достаточно раздавать медиа файлы с поддомен вида usercontent.example.com.

    2. Помимо этого, приложения могут определить список допустимых расширений файлов для загружаемых пользователем файлов и настроить веб-сервер для обслуживания только таких файлов.

Политика безопасности контента

New in Django 6.0.

Политика безопасности контента (CSP) — это механизм безопасности браузера, который помогает защитить веб-приложения от таких атак, как межсайтовый скриптинг (XSS) и других атак путем внедрения контента.

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

Ключевые преимущества включения CSP включают в себя:

  1. Смягчение атак XSS путем блокировки встроенных скриптов и ограничения загрузки внешних скриптов.

  2. Контроль того, какие внешние ресурсы (например, изображения, шрифты, таблицы стилей) могут быть загружены.

  3. Предотвращение нежелательного фрейминга вашего сайта для защиты от кликджекинга.

  4. Отчеты о нарушениях в указанную конечную точку, позволяющие осуществлять мониторинг и отладку.

Инструкции по настройке см. в документации Using CSP и в Обзоре CSP для получения подробной информации о директивах и настройках.

Ограничения и соображения

Хотя CSP является мощным механизмом безопасности, важно понимать его ограничения и последствия, особенно при использовании в Django:

  • Риски исключения политики: избегайте исключения определенных путей или ответов из защиты CSP. Из-за политики браузера по одному и тому же источнику уязвимость на незащищенной странице (например, позволяющая внедрить произвольный скрипт) может быть использована для атаки на защищенные страницы. Исключение любого маршрута может значительно ослабить общую защиту CSP сайта.

  • Накладные расходы на производительность. Хотя CSP обычно незначителен, он добавляет некоторые накладные расходы на обработку. Генерация одноразовых номеров предполагает безопасную случайность для каждого применимого запроса. Для приложений с высоким трафиком или сред с ограниченными ресурсами соответствующим образом измерьте влияние на производительность.

  • Поддержка браузеров. Хотя уровни CSP 1 и 2 широко поддерживаются, новые директивы (уровень CSP 3+) или сложное поведение политик могут различаться в разных браузерах. Проверьте свою политику в средах, которые вы собираетесь поддерживать.

Несмотря на эти ограничения, CSP остается важным и рекомендуемым уровнем безопасности для веб-приложений. Понимание его ограничений поможет вам разработать более эффективное и надежное развертывание.

Дополнительные вопросы безопасности

Несмотря на то, что Django обеспечивает хорошую защиту безопасности «из коробки», по-прежнему важно правильно развернуть ваше приложение и воспользоваться преимуществами защиты веб-сервера, операционной системы и других компонентов.

  • Убедитесь, что ваш код Python находится за пределами корня веб-сервера. Это гарантирует, что ваш код Python не будет случайно использован в виде обычного текста (или случайно выполнен).

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

  • Django не ограничивает запросы на аутентификацию пользователей. Чтобы защититься от атак грубой силы на систему аутентификации, вы можете рассмотреть возможность развертывания плагина Django или модуля веб-сервера для регулирования этих запросов.

  • Держите SECRET_KEY и SECRET_KEY_FALLBACKS, если они используются, в секрете.

  • Хорошей идеей будет ограничить доступ к вашей системе кэширования и к базе данных с помощью фаервола.

  • Обратите внимание на список Топ 10 уязвимостей на сайте Open Web Application Security Project (OWASP). Хотя Django содержит инструменты для защиты от некоторых из них, остальные должны быть учтены в архитектуре вашего проекта.

  • Mozilla обсуждает различные темы, касающиеся «веб-безопасности». На их страницах также описаны принципы безопасности, применимые к любой системе.

Back to Top