Безопасность в 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. -
Используйте «безопасные» куки.
Если браузер первоначально подключается по 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-адресов в определенных случаях. Хотя эти значения очищаются для предотвращения атак межсайтового скриптинга, поддельное значение заголовка 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, требующим развертывания сайта таким образом, чтобы незарегистрированные пользователи не имели доступа к каким-либо поддоменам, 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в секрете. - Рекомендуется ограничить доступ к вашей системе кэширования и базе данных с помощью брандмауэра.
- Изучите список «Топ 10» Проекта по обеспечению безопасности открытых веб-приложений (OWASP) https://www.owasp.org/index.php/Top_10_2013-Top_10, который определяет некоторые распространённые уязвимости в веб-приложениях. Хотя Django имеет инструменты для решения некоторых проблем, к другим вопросам нужно подходить с учётом дизайна вашего проекта.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/2.0/topics/security/