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

Этот документ представляет собой обзор функций безопасности Django. Он включает советы по обеспечению безопасности сайта, работающего на Django.

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

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

Использование шаблонов Django защищает вас от большинства XSS-атак. Однако важно понимать, какую защиту оно обеспечивает и каковы его ограничения.

Django шаблоны escape specific characters, которые особенно опасны для HTML. Хотя это защищает пользователей от большинства вредоносных вводимых данных, это не совсем надежно. Например, это не защитит следующее:

<style class={{ var }}>...</style>

Если var установлено в 'class1 onmouseover=javascript:func()', это может привести к несанкционированному выполнению JavaScript, в зависимости от того, как браузер отображает несовершенный HTML. (Цитирование значения атрибута исправит этот случай).

Также важно быть особенно осторожным при использовании is_safe с пользовательскими тегами шаблонов, тегом шаблона safe, mark_safe, а также при выключенном автоскейпе.

Кроме того, если вы используете систему шаблонов для вывода чего-то, отличного от HTML, могут существовать совершенно отдельные символы и слова, требующие экранирования.

Вы также должны быть очень осторожны при хранении HTML в базе данных, особенно когда этот HTML извлекается и отображается.

Защита от подделки межсайтовых запросов (CSRF)

Атаки CSRF позволяют злоумышленнику выполнить действия, используя учетные данные другого пользователя без его ведома или согласия.

Django имеет встроенную защиту от большинства типов CSRF-атак, при условии, что вы указываете enabled and used it там, где это необходимо. Однако, как и у любой техники защиты, здесь есть свои ограничения. Например, можно отключить модуль CSRF глобально или для определенных представлений. Делать это следует только в том случае, если вы знаете, что делаете. Есть и другие limitations, если ваш сайт имеет поддомены, которые находятся вне вашего контроля.

CSRF protection works путем проверки наличия секрета в каждом POST-запросе. Это гарантирует, что злоумышленник не сможет просто «воспроизвести» форму POST на вашем сайте и заставить другого вошедшего пользователя невольно отправить эту форму. Вредоносный пользователь должен знать секрет, который зависит от конкретного пользователя (с помощью cookie).

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

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

Защита от SQL-инъекций

SQL-инъекция - это тип атаки, при которой злоумышленник может выполнить произвольный SQL-код в базе данных. Это может привести к удалению записей или утечке данных.

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

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

Защита от кликджекинга

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

Django содержит clickjacking protection в виде 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, что является стандартным для большинства браузеров, возможна утечка существующих файлов cookie. По этой причине следует установить настройки SESSION_COOKIE_SECURE и CSRF_COOKIE_SECURE на True. Это даст браузеру указание отправлять эти куки только через HTTPS-соединения. Обратите внимание, что это означает, что сессии не будут работать через HTTP, а защита CSRF не позволит принимать любые данные POST через HTTP (что будет нормально, если вы перенаправляете весь HTTP-трафик на HTTPS).

  • Используйте Строгая транспортная безопасность HTTP (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 может быть использовано для подделки межсайтовых запросов, атак отравления кэша и отравления ссылок в электронных письмах.

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

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

Подобно CSRF limitations, требующему развертывания сайта таким образом, чтобы недоверенные пользователи не имели доступа к поддоменам, django.contrib.sessions также имеет ограничения. Подробнее см. в the session topic guide section on security.

Загружаемый пользователем контент

Примечание

Рассмотрим serving static files from a cloud service or CDN, чтобы избежать некоторых из этих проблем.

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

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

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

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

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

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

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

  • Убедитесь, что ваш код Python находится вне корня веб-сервера. Это гарантирует, что ваш код Python не будет случайно передан в виде обычного текста (или случайно выполнен).
  • Будьте осторожны с любыми user uploaded files.
  • Django не дросселирует запросы на аутентификацию пользователей. Для защиты от атак «грубой силы» на систему аутентификации вы можете рассмотреть возможность установки плагина Django или модуля веб-сервера для дросселирования этих запросов.
  • Держите свой SECRET_KEY в секрете.
  • Хорошей идеей будет ограничить доступ к системе кэширования и базе данных с помощью брандмауэра.
  • Ознакомьтесь с проектом Open Web Application Security Project (OWASP) Top 10 list, который определяет некоторые распространенные уязвимости в веб-приложениях. Хотя Django имеет инструменты для решения некоторых из этих проблем, другие проблемы должны быть учтены при разработке вашего проекта.
Вернуться на верх