Spec-Zone.ru › Flask 3.0

Учет мер безопасности

Веб-приложения обычно сталкиваются со множеством проблем безопасности, и очень сложно все сделать правильно. 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)

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

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

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

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

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

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

  • Secure ограничивает cookie только HTTPS-трафиком.
  • HttpOnly защищает содержимое cookie от чтения с помощью JavaScript.
  • SameSite ограничивает то, как cookie отправляются с запросами со сторонних сайтов. Может быть установлено в 'Lax' (рекомендуется) или 'Strict'. Lax предотвращает отправку cookie с подверженными CSRF запросами со сторонних сайтов, таких как отправка формы. Strict предотвращает отправку cookie со всеми внешними запросами, включая переходы по обычным ссылкам.
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 через заданное время или текущее время плюс возраст соответственно. Если ни один из параметров не установлен, cookie будет удален при закрытии браузера.

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

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

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

  • 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", "")

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

© 2010 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/3.0.x/security/

Spec-Zone.ru

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