демистифицировать Flask app.secret_key

127

Если app.secret_keyне установлен, Flask не позволит вам установить или получить доступ к словарю сеанса.

Это все, что говорится в руководстве пользователя по данной теме.

Я новичок в веб-разработке и понятия не имею, как / почему работают какие-либо средства безопасности. Я хотел бы понять, что делает Flask под капотом.

  • Почему Flask заставляет нас устанавливать это secret_keyсвойство?
  • Как Flask использует secret_keyсвойство?
MYV
источник

Ответы:

102

Все, что требует шифрования (для защиты от взлома злоумышленниками), требует установки секретного ключа. Для только самого Колба, что «все» является Sessionобъектом, но и другие расширения могут использовать тот же секрет.

secret_keyэто просто значение, установленное для SECRET_KEYключа конфигурации, или вы можете установить его напрямую.

В разделе « Сеансы» в Quickstart есть хорошие и разумные советы о том, какой тип секрета на стороне сервера вы должны установить.

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

Flask использует itsdangerousбиблиотеку для выполнения всей тяжелой работы; сеансы используют itsdangerous.URLSafeTimedSerializerкласс с настроенным сериализатором JSON.

Мартейн Питерс
источник
91

Приведенный ниже ответ в первую очередь относится к подписанным файлам cookie - реализации концепции сеансов (используемой в веб-приложениях). Flask предлагает как обычные (неподписанные) файлы cookie (через request.cookiesи response.set_cookie()), так и подписанные файлы cookie (через flask.session). Ответ состоит из двух частей: первая описывает, как создается подписанный файл cookie, а вторая представлена ​​в форме контроля качества, который обращается к различным аспектам схемы. В примерах используется синтаксис Python3, но эти концепции применимы и к предыдущим версиям.

Что это SECRET_KEY(или как создать подписанный файл cookie)?

Подписание файлов cookie - это профилактическая мера против подделки файлов cookie. В процессе подписания файла cookie SECRET_KEYиспользуется аналогично тому, как «соль» используется для запутывания пароля перед его хешированием. Вот (дико) упрощенное описание концепции. Код в примерах предназначен для иллюстрации. Многие шаги были пропущены, и не все функции действительно существуют. Цель здесь - дать понимание общей идеи, фактические реализации будут немного сложнее. Также имейте в виду, что Flask делает большую часть этого за вас в фоновом режиме. Таким образом, помимо установки значений для вашего файла cookie (через API сеанса) и предоставления a SECRET_KEY, не только не рекомендуется переопределить это самостоятельно, но и нет необходимости делать это:

Подпись печенья бедняка

Перед отправкой ответа в браузер:

(1) Сначала SECRET_KEYустанавливается а. Он должен быть известен только приложению и должен оставаться относительно постоянным в течение жизненного цикла приложения, в том числе при перезапуске приложения.

# choose a salt, a secret string of bytes
>>> SECRET_KEY = 'my super secret key'.encode('utf8')

(2) создать файл cookie

>>> cookie = make_cookie(
...     name='_profile', 
...     content='uid=382|membership=regular',
...     ...
...     expires='July 1 2030...'
... )

>>> print(cookie)
name: _profile
content: uid=382|membership=regular...
    ...
    ...
expires: July 1 2030, 1:20:40 AM UTC

(3) для создания подписи добавить (или добавить) SECRET_KEYк байтовой строке cookie, а затем сгенерировать хеш из этой комбинации.

# encode and salt the cookie, then hash the result
>>> cookie_bytes = str(cookie).encode('utf8')
>>> signature = sha1(cookie_bytes+SECRET_KEY).hexdigest()
>>> print(signature)
7ae0e9e033b5fa53aa....

(4) Теперь поставьте подпись на одном конце contentполя исходного файла cookie.

# include signature as part of the cookie
>>> cookie.content = cookie.content + '|' + signature
>>> print(cookie)
name: _profile
content: uid=382|membership=regular|7ae0e9...  <--- signature
domain: .example.com
path: /
send for: Encrypted connections only
expires: July 1 2030, 1:20:40 AM UTC

и это то, что отправляется клиенту.

# add cookie to response
>>> response.set_cookie(cookie)
# send to browser --> 

После получения файла cookie от браузера:

(5) Когда браузер возвращает этот файл cookie обратно на сервер, удалите подпись из contentполя файла cookie, чтобы вернуть исходный файл cookie.

# Upon receiving the cookie from browser
>>> cookie = request.get_cookie()
# pop the signature out of the cookie
>>> (cookie.content, popped_signature) = cookie.content.rsplit('|', 1)

(6) Используйте исходный файл cookie с приложением, SECRET_KEYчтобы пересчитать подпись, используя тот же метод, что и на шаге 3.

# recalculate signature using SECRET_KEY and original cookie
>>> cookie_bytes = str(cookie).encode('utf8')
>>> calculated_signature = sha1(cookie_bytes+SECRET_KEY).hexdigest()

(7) Сравните вычисленный результат с подписью, ранее выдвинутой из только что полученного файла cookie. Если они совпадают, мы знаем, что файл cookie не был испорчен. Но если в куки-файл был добавлен хотя бы пробел, подписи не совпадают.

# if both signatures match, your cookie has not been modified
>>> good_cookie = popped_signature==calculated_signature

(8) Если они не совпадают, вы можете ответить любым количеством действий, зарегистрировать событие, сбросить cookie, создать новый, перенаправить на страницу входа и т. Д.

>>> if not good_cookie:
...     security_log(cookie)

Код аутентификации сообщений на основе хэша (HMAC)

Тип подписи, сгенерированной выше, для которой требуется секретный ключ для обеспечения целостности некоторого содержимого, в криптографии называется кодом аутентификации сообщения или MAC .

Ранее я указывал, что приведенный выше пример является чрезмерным упрощением этой концепции и что реализовывать собственную подпись - не лучшая идея. Это потому, что алгоритм, используемый для подписи файлов cookie во Flask, называется HMAC и немного сложнее, чем приведенный выше простой шаг за шагом. Общая идея та же, но по причинам, выходящим за рамки данного обсуждения, серия вычислений немного сложнее. Если вы все еще заинтересованы в создании DIY, как это обычно бывает, у Python есть несколько модулей, которые помогут вам начать работу :) вот начальный блок:

import hmac
import hashlib

def create_signature(secret_key, msg, digestmod=None):
    if digestmod is None:
        digestmod = hashlib.sha1
    mac = hmac.new(secret_key, msg=msg, digestmod=digestmod)
    return mac.digest()

Документация для hmac и hashlib .


«Демистификация» SECRET_KEY:)

Что в этом контексте «подпись»?

Это метод обеспечения того, чтобы некоторый контент не был изменен кем-либо, кроме человека или организации, уполномоченных на это.

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

Скажем, например, вы собираетесь загрузить исходный код проекта в сжатом файле с веб-зеркала. Контрольная сумма SHA1, опубликованная на веб-странице проекта, - «eb84e8da7ca23e9f83 ....»

# so you get the code from the mirror
download https://mirror.example-codedump.com/source_code.tar.gz
# you calculate the hash as instructed
sha1(source_code.tar.gz)
> eb84e8da7c....

Оба хэша одинаковые, вы знаете, что у вас есть идентичная копия.

Что такое куки?

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

Обычной практикой в ​​веб-приложениях является использование клиента (веб-браузера) в качестве облегченного кеша. Файлы cookie - одно из воплощений этой практики. Cookie - это обычно некоторые данные, добавляемые сервером к HTTP-ответу посредством его заголовков. Он хранится в браузере, который впоследствии отправляет его обратно на сервер при выдаче запросов, в том числе в виде заголовков HTTP. Данные, содержащиеся в файле cookie, могут использоваться для имитации того, что называется сохранением состояния., иллюзия, что сервер поддерживает постоянное соединение с клиентом. Только в этом случае вместо провода, чтобы поддерживать соединение «живым», у вас просто есть снимки состояния приложения после того, как оно обработало запрос клиента. Эти снимки передаются между клиентом и сервером. При получении запроса сервер сначала считывает содержимое файла cookie, чтобы восстановить контекст своего разговора с клиентом. Затем он обрабатывает запрос в этом контексте и, прежде чем вернуть ответ клиенту, обновляет файл cookie. Таким образом сохраняется иллюзия продолжающегося сеанса.

Как выглядит печенье?

Типичный файл cookie будет выглядеть так:

name: _profile
content: uid=382|status=genie
domain: .example.com
path: /
send for: Encrypted connections only
expires: July 1 2030, 1:20:40 AM UTC

Файлы cookie легко просматривать в любом современном браузере. Например, в Firefox перейдите в « Настройки»> «Конфиденциальность»> «История»> «Удалить отдельные файлы cookie» .

contentПоле является наиболее значимым для применения. Другие поля несут в основном метаинструкции для определения различных сфер влияния.

Зачем вообще использовать файлы cookie?

Короткий ответ - производительность. Использование файлов cookie сводит к минимуму необходимость поиска информации в различных хранилищах данных (кеши памяти, файлы, базы данных и т. Д.), Тем самым ускоряя работу серверного приложения. Имейте в виду, что чем больше файл cookie, тем тяжелее нагрузка по сети, поэтому то, что вы сохраняете при поиске в базе данных на сервере, вы можете потерять в сети. Тщательно подумайте, что включить в ваши файлы cookie.

Зачем нужно подписывать файлы cookie?

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

Как можно подделать cookie?

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

Почему SECRET_KEYнеобходимо подписывать файлы cookie?

Проверка файлов cookie немного отличается от проверки исходного кода, как описано ранее. В случае исходного кода первоначальный автор является доверенным лицом и владельцем ссылочного отпечатка пальца (контрольной суммы), который будет общедоступным. Вы не доверяете исходному коду, но доверяете публичной подписи. Итак, чтобы проверить вашу копию источника, вы просто хотите, чтобы ваш вычисленный хеш соответствовал общедоступному хешу.

Однако в случае файла cookie приложение не отслеживает подпись, а отслеживает ее SECRET_KEY. Это SECRET_KEYэталонный отпечаток пальца. Файлы cookie отправляются с подписью, которую они считают законной. Легитимность здесь означает, что подпись была выпущена владельцем файла cookie, то есть приложением, и в данном случае это утверждение, которому вы не доверяете, и вам необходимо проверить подпись на достоверность. Для этого вам нужно включить в подпись элемент, который известен только вам, то есть SECRET_KEY. Кто-то может изменить файл cookie, но, поскольку у них нет секретного ингредиента для правильного расчета действительной подписи, они не могут его подделать. Как было сказано немного ранее, этот тип снятия отпечатков пальцев, когда помимо контрольной суммы также предоставляется секретный ключ,

А как насчет сеансов?

Сеансы в их классической реализации представляют собой файлы cookie, которые содержат только идентификатор в contentполе session_id. Назначение сеансов точно такое же, как и у подписанных файлов cookie, то есть предотвращение подделки файлов cookie. Однако у классических сессий другой подход. После получения файла cookie сеанса сервер использует идентификатор для поиска данных сеанса в собственном локальном хранилище, которым может быть база данных, файл или иногда кеш в памяти. Срок действия файла cookie сеанса обычно истекает при закрытии браузера. Из-за этапа поиска в локальном хранилище такая реализация сеансов обычно приводит к снижению производительности. Подписанные файлы cookie становятся предпочтительной альтернативой, и именно так реализованы сеансы Flask. Другими слова, колбы сессия являетсяподписанные файлы cookie, а для использования подписанных файлов cookie во Flask просто используйте его SessionAPI.

Почему бы также не зашифровать файлы cookie?

Иногда содержимое файлов cookie может быть зашифровано перед подписанием . Это делается, если они считаются слишком уязвимыми для просмотра в браузере (шифрование скрывает содержимое). Однако простая подпись файлов cookie решает другую проблему, когда есть желание поддерживать определенную степень видимости и удобства использования файлов cookie в браузере, предотвращая при этом вмешательство.

Что произойдет, если я изменю SECRET_KEY?

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

Поэтому, если вы не хотите аннулировать все подписанные файлы cookie, постарайтесь сохранить их SECRET_KEYв течение длительного времени.

Что хорошего SECRET_KEY?

Секретный ключ сложно угадать. В документации по сеансам есть хороший рецепт генерации случайных ключей:

>>> import os
>>> os.urandom(24)
'\xfd{H\xe5<\x95\xf9\xe3\x96.5\xd1\x01O<!\xd5\xa2\xa0\x9fR"\xa1\xa8'

Вы копируете ключ и вставляете его в свой файл конфигурации как значение SECRET_KEY.

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

Вы не установить SECRET_KEYнепосредственно с функцией , которая генерирует другой ключ каждый раз , когда он называется. Например, не делайте этого:

# this is not good
SECRET_KEY = random_key_generator()

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

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

Майкл Экока
источник