Spec-Zone.ru › Flask 2.3

Соображения безопасности

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

Межсайтовый скриптинг (XSS)

Межсайтовый скриптинг — это концепция внедрения произвольного HTML (и вместе с ним JavaScript) в контекст веб-сайта. Чтобы исправить это, разработчики должны правильно экранировать текст, чтобы он не мог содержать произвольные теги HTML. Дополнительную информацию об этом можно найти в статье Википедии о межсайтовом скриптинге.

Flask настраивает Jinja2 для автоматической экранизации всех значений, если явно не указано иное. Это должно исключить все проблемы XSS, возникающие в шаблонах, но все же есть другие места, где нужно быть осторожным:

  • формирование HTML без помощи Jinja2
  • вызов Markup на данных, отправленных пользователями
  • отправка HTML из загруженных файлов, никогда этого не делайте, используйте заголовок Content-Disposition: attachment, чтобы предотвратить эту проблему.
  • отправка текстовых файлов из загруженных файлов. Некоторые браузеры используют угадывание типа содержимого на основе первых нескольких байтов, поэтому пользователи могли бы обмануть браузер, чтобы он выполнил HTML.

Еще одна очень важная вещь — это атрибуты без кавычек. Хотя Jinja2 может защитить вас от проблем XSS путем экранирования HTML, есть одна вещь, от которой он не может защитить: XSS через внедрение атрибутов. Чтобы противостоять этому возможному вектору атаки, обязательно заключайте ваши атрибуты в двойные или одинарные кавычки при использовании выражений Jinja в них:

<input value="{{ value }}">

Почему это необходимо? Потому что, если вы этого не сделаете, злоумышленник может легко ввести пользовательские обработчики JavaScript. Например, злоумышленник может ввести этот фрагмент HTML+JavaScript:

onmouseover=alert(document.cookie)

Когда пользователь затем наведёт курсор мыши на поле ввода, куки будет показан пользователю в окне предупреждения. Но вместо того, чтобы показать куки пользователю, хороший злоумышленник может также выполнить любой другой код JavaScript. В сочетании с внедрениями CSS злоумышленник может даже заставить элемент заполнить всю страницу, так что пользователю нужно будет просто навести курсор мыши на любую часть страницы, чтобы запустить атаку.

Существует один класс проблем XSS, от которых экранирование Jinja не защищает. Атрибут href тега a может содержать javascript: URI, который браузер выполнит при нажатии, если он не защищен должным образом.

<a href="{{ value }}">click here</a>
<a href="javascript:alert('unsafe');">click here</a>

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

Межсайтовая подделка запроса (CSRF)

Еще одна большая проблема — CSRF. Это очень сложная тема, и я не буду подробно её описывать здесь, просто упомяну, что это такое и как теоретически её предотвратить.

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

Допустим, у вас есть определённый URL, который, при отправке запросов POST к нему, удалит профиль пользователя (скажем, http://example.com/user/delete). Если теперь злоумышленник создаст страницу, которая отправляет POST-запрос на эту страницу с помощью JavaScript, ему нужно лишь обмануть некоторых пользователей, чтобы они загрузили эту страницу, и их профили будут удалены.

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

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

Почему Flask не делает это за вас? Идеальное место для этого — фреймворк валидации форм, которого нет в Flask.

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

В Flask 0.10 и ниже, jsonify() не сериализовал массивы верхнего уровня в JSON. Это было из-за уязвимости безопасности в ECMAScript 4.

ECMAScript 5 закрыл эту уязвимость, поэтому уязвимы только очень старые браузеры. Все эти браузеры имеют другие более серьезные уязвимости, поэтому это поведение было изменено, и jsonify() теперь поддерживает сериализацию массивов.

Заголовки безопасности

Браузеры распознают различные заголовки ответа для управления безопасностью. Мы рекомендуем просмотреть каждый из перечисленных заголовков для использования в вашем приложении. Расширение Flask-Talisman может использоваться для управления HTTPS и заголовками безопасности за вас.

HTTP Strict Transport Security (HSTS)

Указывает браузеру преобразовывать все HTTP-запросы в HTTPS, предотвращая атаки «человек посередине» (MITM).

response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
  • https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security

Политика безопасности содержимого (CSP)

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

response.headers['Content-Security-Policy'] = "default-src 'self'"
  • https://csp.withgoogle.com/docs/index.html
  • https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy

X-Content-Type-Options

Принуждает браузер соблюдать тип содержимого ответа вместо попытки его определения, что может быть использовано для создания атаки межсайтового скриптинга (XSS).

response.headers['X-Content-Type-Options'] = 'nosniff'
  • https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options

X-Frame-Options

Предотвращает сторонним сайтам встраивание вашего сайта в iframe. Это предотвращает класс атак, где щелчки во внешней рамке могут быть незаметно переведены в щелчки по элементам вашей страницы. Это также известно как «кликиджекинг».

response.headers['X-Frame-Options'] = 'SAMEORIGIN'
  • https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options

Параметры Set-Cookie

Эти параметры можно добавить в заголовок Set-Cookie для повышения их безопасности. Flask имеет параметры конфигурации для установки этих параметров для куки сессии. Их можно установить и для других куки.

  • Secure ограничивает куки только HTTPS-трафиком.
  • HttpOnly защищает содержимое куки от считывания с помощью JavaScript.
  • SameSite ограничивает, как куки отправляются с запросами со сторонних сайтов. Может быть установлено в 'Lax' (рекомендуется) или 'Strict'. Lax предотвращает отправку куки с подверженными CSRF-атакам запросам со сторонних сайтов, таких как отправка формы. Strict предотвращает отправку куки со всеми внешними запросами, включая переход по обычным ссылкам.
app.config.update(
    SESSION_COOKIE_SECURE=True,
    SESSION_COOKIE_HTTPONLY=True,
    SESSION_COOKIE_SAMESITE='Lax',
)

response.set_cookie('username', 'flask', secure=True, httponly=True, samesite='Lax')

Указание параметров Expires или Max-Age удалит куки после заданного времени или текущего времени плюс возраст, соответственно. Если ни один параметр не установлен, куки будет удалён при закрытии браузера.

# cookie expires after 10 minutes
response.set_cookie('snakes', '3', max_age=600)

Для куки сессии, если session.permanent установлен, то PERMANENT_SESSION_LIFETIME используется для установки срока действия. Реализация куки Flask проверяет, что криптографическая подпись не старше этого значения. Уменьшение этого значения может помочь смягчить атаки с повторным использованием, где перехваченные куки могут быть отправлены позже.

app.config.update(
    PERMANENT_SESSION_LIFETIME=600
)

@app.route('/login', methods=['POST'])
def login():
    ...
    session.clear()
    session['user_id'] = user.id
    session.permanent = True
    ...

Используйте itsdangerous.TimedSerializer для подписи и проверки других значений куки (или любых значений, которые требуют безопасных подписей).

  • https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies
  • https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie

HTTP Public Key Pinning (HPKP)

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

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

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

  • https://developer.mozilla.org/en-US/docs/Web/HTTP/Public_Key_Pinning

Копирование/вставка в терминал

Скрытые символы, такие как символ удаления (\b, ^H) могут привести к отображению текста в HTML не так, как он интерпретируется при вставке в терминал в терминал.

Например, import y\bose\bm\bi\bt\be\b отображается как import yosemite в HTML, но удаления применяются при вставке в терминал, и он становится import os.

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

body = body.replace("\b", "")

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

END_OF_DOCUMENT_MARKER

© 2007–2022 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/2.3.x/security/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API