Effets de la modification de SECRET_KEY de Django

202

J'ai fait une erreur et enregistré mes projets Django SECRET_KEYdans un référentiel public.

Cette clé aurait dû être gardée secrète selon les documents https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-SECRET_KEY

Le projet Django est en ligne et fonctionne depuis un certain temps avec certains utilisateurs actifs. Quels sont les effets si je change le SECRET_KEY? Les utilisateurs, cookies, sessions, etc. existants seront-ils affectés? De toute évidence, le nouveau SECRET_KEYne sera plus stocké dans un lieu public.

Derek Kwok
la source

Réponses:

199

Edit: Cette réponse est basée sur Django 1.5

SECRET_KEY est utilisé dans de nombreux endroits différents, je vais d'abord souligner ce qui en est affecté, puis essayer de parcourir cette liste et de donner une explication précise de l'impact.

La liste des choses utilisant SECRET_KEYdirectement ou indirectement:

En réalité , beaucoup des éléments énumérés ici utiliser à SECRET_KEYtravers django.utils.crypt.get_random_string()lequel il utilise pour semer le moteur aléatoire. Cela ne sera pas affecté par un changement de valeur de SECRET_KEY.

L'expérience utilisateur directement impactée par un changement de valeur est:

  • sessions, le décodage des données sera interrompu, ce qui est valable pour tout backend de session (cookies, base de données, fichier ou cache).
  • le jeton de réinitialisation du mot de passe déjà envoyé ne fonctionnera pas, les utilisateurs devront en demander un nouveau.
  • le formulaire de commentaires (si utilisé django.contrib.comments) ne validera pas s'il a été demandé avant le changement de valeur et soumis après le changement de valeur. Je pense que c'est très mineur mais peut être déroutant pour l'utilisateur.
  • les messages (de django.contrib.messages) ne valideront pas côté serveur dans les mêmes conditions de temps que pour le formulaire de commentaires.

MISE À JOUR : travaillant maintenant sur django 1.9.5, un rapide coup d'œil à la source me donne à peu près les mêmes réponses. Pourrait faire une inspection approfondie plus tard.

sberder
la source
1
Je modifie SECRET_KEY sur mon serveur de développement local et cela ne me déconnecte pas, il semble donc qu'au moins les sessions (cache) fonctionnent correctement après le changement. Pourriez-vous développer davantage ce que vous entendez par data decode will breaket peut-être signaler du code (dans django ou un exemple de projet) qui se brisera? EDIT: utilise toujours django 1.4 - est-ce le cas?
Kirill Zaitsev
@teferi Je ne connais pas 1.4, c'est une question de regarder le code. J'ai pointé toutes les sources pour chaque point, vous pouvez jeter un oeil à "protéger les données de session et créer des clés de session aléatoires". Il est normal que vous soyez toujours connecté, mais vous ne pourrez pas lire les données contenues dans la session car elles SECRET_KEYsont salted_hmacutilisées pour hacher les données de session.
sberder
s'il est utilisé pour le sel de hachage de mot de passe, cela ne signifie-t-il pas que les mots de passe dans la base de données doivent être réinitialisés?
Henning
7
@ Henning, je ne pense pas. Les mots de passe sont stockés comme <algorithm>$<iterations>$<salt>$<hash>dans auth_user, donc le sel aléatoire est stocké avec le mot de passe dans chaque cas.
Denis Drescher
2
La réponse serait-elle considérablement différente dans les versions de Django> 1.5? (par exemple la version actuelle 1.9)
das-g
36

Depuis que cette question a été posée, la documentation de Django a changé pour inclure une réponse.

La clé secrète est utilisée pour:

  • Toutes les sessions si vous utilisez un autre backend de session que django.contrib.sessions.backends.cache, ou utilisez la valeur par défaut get_session_auth_hash().
  • Tous les messages si vous utilisez CookieStorageou FallbackStorage.
  • Tous les PasswordResetViewjetons.
  • Toute utilisation de la signature cryptographique, sauf si une clé différente est fournie.

Si vous faites pivoter votre clé secrète, tout ce qui précède sera invalidé. Les clés secrètes ne sont pas utilisées pour les mots de passe des utilisateurs et la rotation des clés ne les affectera pas.

Je ne savais pas exactement comment je devais faire pivoter la clé secrète. J'ai trouvé une discussion sur la façon dont Django génère une clé pour un nouveau projet , ainsi qu'un Gist qui discute d' autres options . J'ai finalement décidé de simplement demander à Django de créer un nouveau projet, de copier la nouvelle clé secrète dans mon ancien projet, puis d' effacer le nouveau projet .

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

Mettre à jour

Il semble que Django ait ajouté la get_random_secret_key()fonction dans la version 1.10. Vous pouvez l'utiliser pour générer une nouvelle clé secrète.

$ ./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
$
Don Kirkby
la source
4
La génération de clé secrète repose-t-elle sur la clé secrète?
kdazzle
4
Non, @kdazzle, si vous regardez le code sourcestartproject , vous pouvez voir qu'il génère simplement une chaîne aléatoire en utilisant le cryptomodule.
Don Kirkby
12
Heh, désolé, @DonKirkby, mauvaise blague
kdazzle
16

Selon cette page https://docs.djangoproject.com/en/dev/topics/signing/ , SECRET_KEY est principalement utilisé pour les trucs transitoires - signature de données envoyées sur le fil afin que vous puissiez détecter la falsification, par exemple. Il semble que les choses qui POURRAIENT casser sont:

  • Cookies signés, par exemple des valeurs de type "mémoriser mon authentification sur cet ordinateur". Dans ce cas, le cookie sera invalidé, la signature ne sera pas vérifiée et l'utilisateur devra se ré-authentifier.
  • Pour tous les utilisateurs qui ont demandé des liens pour une réinitialisation de mot de passe ou un téléchargement de fichier personnalisé, ces liens ne seront plus valides. Les utilisateurs devraient simplement demander à nouveau ces liens.

Quelqu'un avec une expérience Django plus récente et / ou saillante que moi pourrait sonner autrement, mais je soupçonne qu'à moins que vous ne fassiez explicitement quelque chose avec l'API de signature, cela ne devrait que créer un léger inconvénient pour vos utilisateurs.

Tim Keating
la source
6
Alors pourquoi ne pas générer une nouvelle clé à chaque redémarrage du serveur?
osa
4
Cela provoquerait probablement un problème si vous exécutez le même serveur en utilisant plusieurs processus.
dbn
1
@osa voudriez-vous déconnecter TOUS vos utilisateurs à chaque fois que vous envoyez du code / redémarrez votre serveur?
EralpB
6

La chaîne SECRET_KEY est principalement utilisée pour chiffrer et / ou hacher les données des cookies. De nombreux frameworks (y compris Django) y parviennent, car les cookies de session par défaut ont leurs propres inconvénients.

Imaginez que vous avez un formulaire dans django pour éditer des articles avec un champ caché. Dans ce champ caché se trouve l'identifiant de l'article que vous avez modifié. Et si vous voulez être sûr que personne ne peut vous envoyer d'autre identifiant d'article, vous ajouterez un champ caché supplémentaire avec un identifiant haché. Donc, si quelqu'un change l'identifiant, vous le saurez car le hachage ne sera pas le même.

Bien sûr, ceci est un exemple trivial, mais c'est ainsi que SECRET_KEY est utilisé.

Django l'utilise en interne par exemple pour {% csrf_token%} et quelques autres choses. Cela ne devrait vraiment pas avoir d'impact sur votre application si vous la modifiez en fonction de votre question et que vous ne l'utilisez pas.

La seule chose est que peut - être les valeurs de session seront supprimées. Ainsi, par exemple, les utilisateurs devront se reconnecter à l'administrateur, car django ne pourra pas décoder la session avec une clé différente.

sans obscurité
la source
1

J'ai fait la même erreur. Le mot de passe par défaut était long de 50 donc j'ai utilisé PowerShell pour générer une longue chaîne aléatoire de 50 et j'ai remplacé l'ancien SECRET_KEY avec. J'étais connecté et après avoir remplacé SECRET_KEY, ma session précédente avait été invalidée.

Avec Powershell ( source ):

# 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)

Avec Bash ( source ):

# 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

À ce stade, j'ai pensé pourquoi ne pas essayer une clé plus grande, alors je l'ai essayée avec une clé longue de 100 et 1000. Les deux ont fonctionné. Si je comprends le code source , l'objet renvoyé par la fonction de signataire est un hachage hmac en base64. RFC 2104 a ceci à dire pour la longueur requise d'une clé secrète HMAC.

Les applications qui utilisent des clés plus longues que B octets hachent d'abord la clé à l'aide de H, puis utilisent la chaîne d'octets L résultante comme clé réelle de HMAC.

La clé pour HMAC peut être de n'importe quelle longueur (les clés plus longues que B octets sont d'abord hachées à l'aide de H). Cependant, moins de L octets est fortement déconseillé car cela diminuerait la sécurité de la fonction. Les clés plus longues que L octets sont acceptables mais la longueur supplémentaire n'augmenterait pas de manière significative la force de la fonction. (Une clé plus longue peut être recommandée si le caractère aléatoire de la clé est considéré comme faible.)

Pour traduire en langage normal, la taille de la clé secrète doit être la même que celle de la sortie. La clé doit également être en bits. Chaque chiffre en base64 représente 6 bits. Donc, si vous aviez un mot de passe de 50 caractères, vous auriez une clé secrète 50 x 6 = 300 bits. Si vous utilisez SHA256, vous aurez alors besoin d'une clé de 256 bits ( sha256 utilise 256 bits par définition ). Par conséquent, un mot de passe long de 50 devrait fonctionner, sauf si vous prévoyez d'utiliser un algorithme de hachage plus grand que SHA256.

Mais comme tous les bits supplémentaires de la clé sont hachés, leur taille ne diminuera pas considérablement les performances. Mais cela vous garantirait que vous avez suffisamment de bits pour des fonctions de hachage plus importantes. SHA-512 serait couvert par une SECRET_KEY longue de 100 ( 50 x 6 = 600 bits> 512 bits ).

Rex Linder
la source