Spec-Zone.ru › Flask 2.2

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

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

<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, предотвращая атаки типа «man-in-the-middle» (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", "")

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

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

Spec-Zone.ru

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