Ефекти зміни SECRET_KEY Django


202

Я допустив помилку і переклав проект «Джанго» SECRET_KEYу загальнодоступне сховище.

Цей ключ повинен бути збережений у таємниці відповідно до документів https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-SECRET_KEY

Проект "Джанго" працює в реальному часі і працює деякий час з деякими активними користувачами. Які ефекти, якщо я змінити SECRET_KEY? Чи вплинуть будь-які існуючі користувачі, файли cookie, сеанси тощо? Очевидно, що нове SECRET_KEYбільше не зберігатиметься у загальнодоступному місці.

Відповіді:


199

Редагувати: Ця відповідь заснована на django 1.5

SECRET_KEY використовується в багатьох різних місцях, я спершу зазначу, на що це впливає, а потім спробую перейти до цього списку і дати точне пояснення впливу.

Перелік речей, що використовують SECRET_KEYпрямо або опосередковано:

Насправді багато перерахованих тут предметів використовують, за SECRET_KEYдопомогою django.utils.crypt.get_random_string()яких використовується для зародження випадкових механізмів. На це не вплине зміна вартості SECRET_KEY.

На досвід користувача, на який безпосередньо впливає зміна значення, є:

  • сеансів, декодування даних порушиться, що справедливо для будь-якого бекенда сеансу (файли cookie, база даних, файли або кеш).
  • Уже відправлений маркер скидання пароля не працює, користувачі повинні будуть запитати новий.
  • Форма коментарів (якщо використовується django.contrib.comments) не буде підтвердженою, якщо її було запропоновано до зміни значення та подано після зміни значення. Я думаю, це дуже незначно, але це може заплутати користувачів.
  • повідомлення (від django.contrib.messages) не перевірять сторону сервера в тих самих умовах часу, що і для форми коментарів.

ОНОВЛЕННЯ : зараз працюю над django 1.9.5, швидкий погляд на джерело дає мені майже однакові відповіді. Можливо, пізніше провести ретельний огляд.


1
Я змінюю SECRET_KEY на своєму локальному сервері розробників, і це не виходило з системи, тому, здається, що принаймні сеанси (кеш) працюють правильно після зміни. Не могли б ви детальніше data decode will breakрозібратися, що ви маєте на увазі під собою, і, можливо, вказати якийсь код (у django чи приклад проекту), який порушиться? EDIT: все ще використовується django 1.4 - це так?
Кирило Зайцев

@teferi Я не знаю про 1.4, це питання подивитися на код. Я вказав на всі джерела для кожної точки, ви можете подивитися на "захист даних сеансу та створення випадкових ключів сеансу". Це нормально, що ви все ще входите в систему, але ви не зможете читати дані, що містяться в сеансі, як SECRET_KEYце salted_hmacвикористовується для хешування даних сеансу.
sberder

якщо він використовується для солі хешу для паролів, чи не означає це, що паролі в базі даних повинні бути скинуті?
Хеннінг

7
@Henning Я так не думаю. Ці паролі зберігаються в вигляді <algorithm>$<iterations>$<salt>$<hash>в AUTH_USER, тому випадкова сіль зберігається разом з паролем в кожному конкретному випадку.
Денис Дрешер

2
Чи відрізнятиметься відповідь у версіях Джанго> 1.5? (наприклад, теперішній 1.9)
das-g

36

Оскільки це запитання було задано, документація Джанго змінилася, включаючи відповідь.

Секретний ключ використовується для:

  • Всі сесії , якщо ви використовуєте який - або інший сеанс бекенд , ніж django.contrib.sessions.backends.cache, або використовуєте за замовчуванням get_session_auth_hash().
  • Усі повідомлення, якщо ви використовуєте CookieStorageабо FallbackStorage.
  • Усі PasswordResetViewжетони
  • Будь-яке використання криптографічного підпису, якщо не вказано інший ключ.

Якщо ви повернете секретний ключ, все вищезазначене буде визнано недійсним. Секретні ключі не використовуються для паролів користувачів і поворот ключів на них не вплине.

Мені було не ясно, як саме я повинен повертати секретний ключ. Я знайшов дискусію про те, як Джанго генерує ключ для нового проекту , а також історію, яка обговорює інші варіанти . Нарешті я вирішив просто змусити Джанго створити новий проект, скопіювати новий секретний ключ у мій старий проект, а потім стерти новий проект .

cd ~/junk # Go to some safe directory to create a new project.
django-admin startproject django_scratch
grep SECRET_KEY django_scratch/django_scratch/settings.py # copy to old project
rm -R django_scratch

Оновлення

Схоже, Джанго додав get_random_secret_key()функцію у версії 1.10. Ви можете використовувати це для створення нового секретного ключа.

$ ./manage.py shell -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
s!)5@5s79sp=92a+!f4v!1g0d0+64ln3d$xm1f_7=749ht&-zi
$ ./manage.py shell -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
_)+%kymd=f^8o_fea1*yro7atz3w+5(t2/lm2cz70*e$2mn\g3
$

4
Чи покладається секретний ключ на секретний ключ?
kdazzle

4
Ні, @kdazzle, якщо подивитися на вихідний код дляstartproject , ви можете побачити, що він просто генерує випадкову рядок за допомогою cryptoмодуля.
Дон Кіркбі

12
Хе, вибачте, @DonKirkby, поганий жарт
kdazzle

16

Відповідно до цієї сторінки https://docs.djangoproject.com/en/dev/topics/signing/ , SECRET_KEY в основному використовується для перехідних речей - для підписання даних, що надсилаються по дроту, щоб ви могли виявити, наприклад, підробку. Це схоже на речі, які МОЖЕ зламати:

  • Підписані файли cookie, наприклад, значення типу "запам'ятати мій автор на цьому комп'ютері". У цьому випадку файл cookie буде недійсним, підпис не вдасться перевірити, і користувачеві доведеться повторно підтвердити автентифікацію.
  • Для будь-яких користувачів, які попросили посилання для скидання пароля або завантаження користувальницького файлу, ці посилання більше не будуть дійсними. Користувачам просто доведеться повторно запитувати ці посилання.

Хтось із більш недавнім та / або помітним досвідом Джанго, ніж я, може подзвонити в іншому випадку, але я підозрюю, що, якщо ви явно не робите щось з API підписання, це може створювати лише легкі незручності для ваших користувачів.


6
Тоді чому б не створити новий ключ при кожному перезапуску сервера?
оса

4
Можливо, це призведе до проблеми, якщо ви використовуєте один і той же сервер, використовуючи кілька процесів.
dbn

1
@osa Ви хочете вийти зі всіх своїх користувачів кожного разу, коли ви натискаєте код / ​​перезапускаєте сервер?
EralpB

6

Рядок SECRET_KEY використовується в основному для шифрування та / або хешування даних cookie. Дуже багато фреймворків (включаючи Django) приходять до цього, оскільки файли cookie сеансу за замовчуванням мають свої недоліки.

Уявіть, що у вас є форма в django для редагування статей із прихованим полем. У цьому прихованому полі зберігається ідентифікатор статті, яку ви редагували. І якщо ви хочете бути впевнені, що ніхто не може надіслати вам будь-який інший ідентифікатор статті, ви додасте додаткове приховане поле з хешованим ідентифікатором. Тож якщо хтось змінить ідентифікатор, ви дізнаєтесь це, оскільки хеш не буде таким.

Звичайно, це тривіальний приклад, але для цього використовується SECRET_KEY.

Django використовує його, наприклад, для {% csrf_token%} та ще декількох речей. Це дійсно не повинно впливати на вашу програму, якщо ви її зміните, виходячи з вашого запитання та не використовуючи її.

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


1

Я зробив цю саму помилку. Пароль за замовчуванням був 50 довгим, тому я використав shellhell для створення 50 довгих випадкових рядків і замінив на нього старий SECRET_KEY. Я ввійшов у систему і після заміни SECRET_KEY попередній сеанс був визнаний недійсним.

З Powershell ( джерело ):

# Load the .net System.Web namespace which has the GeneratePassword function
[Reflection.Assembly]::LoadWithPartialName("System.Web")

#  GeneratePassword(int length, int numberOfNonAlphanumericCharacters)
[System.Web.Security.Membership]::GeneratePassword(50,5)

З Bash ( джерело ):

# tr includes ABCabc123 and the characters from OWASP's "Password special characters list"
cat /dev/urandom | tr -dc 'A-Za-z0-9!"#$%&\''()*+,-./:;<=>?@[\]^_`{|}~' | head -c 100 ; echo

У цей момент я подумав, чому б не спробувати більший ключ, тому спробував його з клавішею довжиною 100 і 1000. Обидва працювали. Якщо я розумію вихідний код , об'єктом, який повертається функцією підписання, є хмаковий хеш у base64. RFC 2104 має на увазі необхідну довжину секретного ключа HMAC.

Програми, які використовують ключі довше B байтів, спочатку хешують ключ за допомогою H, а потім використовують результуючу рядок байтів L як фактичний ключ до HMAC.

Ключ для HMAC може бути будь-якої довжини (клавіші довше B байтів спочатку хешируються за допомогою H). Однак менше L байтів сильно не рекомендується, оскільки це знизить рівень безпеки функції. Клавіші довше L байтів є прийнятними, але додаткова довжина не суттєво збільшила б функціональну силу. (Більш довгий ключ може бути доцільним, якщо випадковість ключа вважається слабкою.)

Для перекладу на звичайну розмову розмір секретного ключа повинен бути такого ж розміру, що і вихідний. Ключ також повинен бути в бітах. Кожна цифра в base64 представляє 6 біт. Отже, якби у вас був 50-символьний пароль, у вас був би секретний ключ 50 x 6 = 300 біт. Якщо ви використовуєте SHA256, то вам знадобиться 256-бітний ключ ( sha256 використовує 256 біт за визначенням ). Таким чином, 50-ти довгий пароль повинен працювати, якщо ви не плануєте використовувати алгоритм хешування, більший за SHA256.

Але оскільки будь-які зайві біти в ключі хешируються, розмір його не буде різко знижувати продуктивність. Але це би гарантувало вам, що у вас є достатня кількість бітів для великих хеш-функцій. SHA-512 буде охоплено 100 довгим SECRET_KEY ( 50 x 6 = 600 біт> 512 біт ).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.