Spec-Zone.ru › Flask 2.1

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

Веб-приложения обычно сталкиваются со всевозможными проблемами безопасности, и очень сложно сделать всё правильно. 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. Это предотвращает класс атак, где клики во внешней рамке могут быть невидимо переведены в клики по элементам вашей страницы. Это также известно как «clickjacking».

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

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

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

Spec-Zone.ru

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