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

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

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

XSS атаки позволяют пользователю вставить собственные JS скрипты в браузеры других пользователей. Это достигается с помощью сохранения вредоносных скриптов в базе данных, которые затем запрашиваются и отображаются браузерами других пользователей, или принуждением пользователя нажать на ссылку, которая позволит вредоносному скрипту выполниться в браузере пользователя. Однако, 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 ORM созданный SQL запрос будет правильно экранирован соответствующим драйвером базы данных. Однако, Django предоставляет разработчикам возможность писать запросы напрямую или выполнять собственные запросы. Эти возможности следует использовать умеренно и всегда обращать пристальное внимание на экранирование всех параметров, которые предоставлены пользователем. Такое следует проявлять осторожность при использовании extra().

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

Clickjacking is a type of attack where a malicious site wraps another site in a frame. This attack can result in an unsuspecting user being tricked into performing unintended actions on the target site.

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

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

SSL/HTTPS

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

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

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

  • Настройте перенаправление HTTP запросов на HTTPS.

    Это может быть сделано с помощью своего middleware. Пожалуйста, обратите внимание на недостатки 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 обычно настраивается на веб сервере.

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

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

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

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

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

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

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

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

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

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

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

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

  • Код вашего приложения должен находиться вне корня веб сервера. Это не позволит случайно отобразить его в виде текста или выполнить его.

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

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

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

  • Храните содержимое параметра SECRET_KEY в секрете.

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