Effetti della modifica del SECRET_KEY di Django


202

Ho fatto un errore e ho SECRET_KEYinserito il mio progetto Django in un archivio pubblico.

Questa chiave avrebbe dovuto essere mantenuta segreta secondo i documenti https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-SECRET_KEY

Il progetto Django è attivo ed è in corso da un po 'di tempo con alcuni utenti attivi. Quali sono gli effetti se cambio SECRET_KEY? Saranno interessati utenti, cookie, sessioni ecc. Esistenti? Ovviamente, il nuovo SECRET_KEYnon verrà più archiviato in un luogo pubblico.

Risposte:


199

Modifica: questa risposta si basa su django 1.5

SECRET_KEY è usato in molti posti diversi, ti segnalo prima cosa ne è influenzato e poi proverò a ripassare quell'elenco e dare una spiegazione precisa dell'impatto.

L'elenco delle cose usando SECRET_KEYdirettamente o indirettamente:

In realtà molti degli oggetti elencati qui usano SECRET_KEYattraverso i django.utils.crypt.get_random_string()quali lo usa per seminare il motore casuale. Questo non sarà influenzato da una modifica del valore di SECRET_KEY.

L'esperienza dell'utente direttamente influenzata da una variazione di valore sono:

  • sessioni, la decodifica dei dati si interromperà, valida per qualsiasi backend di sessione (cookie, database, basato su file o cache).
  • il token di reimpostazione password già inviato non funzionerà, gli utenti dovranno richiederne uno nuovo.
  • il modulo dei commenti (se utilizzato django.contrib.comments) non verrà convalidato se è stato richiesto prima della modifica del valore e inviato dopo la modifica del valore. Penso che questo sia molto minore ma potrebbe essere fonte di confusione per l'utente.
  • i messaggi (da django.contrib.messages) non convalideranno sul lato server nelle stesse condizioni di temporizzazione del modulo dei commenti.

AGGIORNAMENTO : ora lavorando su Django 1.9.5, una rapida occhiata alla fonte mi dà praticamente le stesse risposte. Potrebbe fare un'ispezione approfondita in seguito.


1
Sto cambiando SECRET_KEY sul mio server di sviluppo locale e questo non mi disconnette, quindi sembra che almeno le sessioni (cache) funzionino correttamente dopo la modifica. Potresti per favore approfondire ulteriormente cosa intendi con data decode will breake forse indicare un codice (in django o esempio di progetto) che si romperà? EDIT: usando ancora django 1.4 - è così?
Kirill Zaitsev il

@teferi Non so 1.4, si tratta di dare un'occhiata al codice. Ho indicato tutte le fonti per ogni punto, puoi dare un'occhiata a "proteggere i dati della sessione e creare chiavi di sessione casuali". È normale che tu abbia ancora effettuato l'accesso ma non sarai in grado di leggere i dati contenuti nella sessione così come SECRET_KEYvengono utilizzati per salted_hmaceseguire l'hash dei dati della sessione.
sberder

se viene utilizzato per la password hash salt, ciò non significa che le password nel database devono essere ripristinate?
Henning,

7
@Henning Non la penso così. Le password sono memorizzate come <algorithm>$<iterations>$<salt>$<hash>in auth_user, quindi il salt casuale viene memorizzato accanto alla password in ogni caso.
Denis Drescher,

2
La risposta sarebbe significativamente diversa nelle versioni Django> 1.5? (es. l'attuale 1.9)
das-g

36

Da quando questa domanda è stata posta, la documentazione di Django è cambiata per includere una risposta.

La chiave segreta viene utilizzata per:

  • Tutte le sessioni se si utilizza un back-end di sessione diverso da django.contrib.sessions.backends.cacheo si utilizza l'impostazione predefinita get_session_auth_hash().
  • Tutti i messaggi se si sta utilizzando CookieStorageo FallbackStorage.
  • Tutti i PasswordResetViewtoken.
  • Qualsiasi utilizzo della firma crittografica, a meno che non venga fornita una chiave diversa.

Se si ruota la chiave segreta, tutto quanto sopra verrà invalidato. Le chiavi segrete non vengono utilizzate per le password degli utenti e la rotazione delle chiavi non li influenzerà.

Non mi era chiaro esattamente come avrei dovuto ruotare la chiave segreta. Ho trovato una discussione su come Django genera una chiave per un nuovo progetto , oltre a un Gist che discute di altre opzioni . Alla fine ho deciso di convincere Django a creare un nuovo progetto, copiare la nuova chiave segreta nel mio vecchio progetto e quindi cancellare il nuovo progetto .

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

Aggiornare

Sembra che Django abbia aggiunto la get_random_secret_key()funzione nella versione 1.10. Puoi usarlo per generare una nuova chiave segreta.

$ ./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
La generazione di chiavi segrete si basa sulla chiave segreta?
kdazzle,

4
No, @kdazzle, se guardi il codice sorgente perstartproject , puoi vedere che genera semplicemente una stringa casuale usando il cryptomodulo.
Don Kirkby,

12
Heh, scusa, @DonKirkby, brutta battuta
kdazzle,

16

Secondo questa pagina https://docs.djangoproject.com/en/dev/topics/signing/ , SECRET_KEY viene utilizzato principalmente per elementi transitori: firma dei dati inviati tramite il filo in modo da poter rilevare manomissioni, ad esempio. Sembra che le cose che POTREBBERO rompere siano:

  • Cookie firmati, ad es. Valori di tipo "ricorda la mia autenticazione su questo computer". In questo caso, il cookie verrà invalidato, la firma non verrà verificata e l'utente dovrà eseguire nuovamente l'autenticazione.
  • Per tutti gli utenti che hanno richiesto collegamenti per reimpostare la password o scaricare file personalizzati, tali collegamenti non saranno più validi. Gli utenti dovrebbero semplicemente richiedere nuovamente tali collegamenti.

Qualcuno con un'esperienza Django più recente e / o saliente di me potrebbe intervenire altrimenti, ma sospetto che a meno che tu non stia facendo esplicitamente qualcosa con l'API di firma, questo dovrebbe solo creare un lieve inconveniente per i tuoi utenti.


6
Quindi perché non generare una nuova chiave ad ogni riavvio del server?
osa,

4
Probabilmente causerebbe un problema se si esegue lo stesso server utilizzando più processi.
dbn,

1
@osa vorresti disconnettere TUTTI i tuoi utenti ogni volta che premi il codice / riavvii il tuo server?
EralpB,

6

La stringa SECRET_KEY viene utilizzata principalmente per la crittografia e / o l'hashing dei dati dei cookie. Molti framework (incluso Django) arrivano a questo dato che i cookie di sessione predefiniti hanno i loro svantaggi.

Immagina di avere forma in django per la modifica di articoli con un campo nascosto. In questo campo nascosto è memorizzato l'ID dell'articolo che hai modificato. E se vuoi essere sicuro che nessuno possa inviarti altri ID articolo, aggiungi un campo nascosto aggiuntivo con ID con hash. Quindi, se qualcuno cambierà l'ID, lo saprai perché l'hash non sarà lo stesso.

Ovviamente questo è un esempio banale ma è così che viene utilizzato SECRET_KEY.

Django lo utilizza internamente, ad esempio per {% csrf_token%} e poche altre cose. In realtà non dovrebbe avere alcun impatto sulla tua applicazione se la cambi, in base alla tua domanda e che non la stai usando.

L'unica cosa è che forse i valori della sessione verranno eliminati. Quindi, ad esempio, gli utenti dovranno accedere nuovamente ad admin, perché django non sarà in grado di decodificare la sessione con chiave diversa.


1

Ho fatto questo stesso errore. La password predefinita era 50, quindi ho usato PowerShell per generare una stringa casuale lunga 50 e ho sostituito il vecchio SECRET_KEY con esso. Ho effettuato l'accesso e dopo aver sostituito SECRET_KEY la mia sessione precedente era stata invalidata.

Con Powershell ( fonte ):

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

Con Bash ( fonte ):

# 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

A questo punto ho pensato perché non provare una chiave più grande, quindi l'ho provata con una chiave lunga 100 e 1000. Entrambi hanno funzionato. Se capisco il codice sorgente , l'oggetto restituito dalla funzione di firma è un hash hmac in base64. RFC 2104 dice questo per la lunghezza richiesta di una chiave segreta HMAC.

Le applicazioni che usano chiavi più lunghe di B byte eseguiranno prima l'hashing della chiave usando H, quindi la stringa L byte risultante come chiave effettiva di HMAC.

La chiave per HMAC può essere di qualsiasi lunghezza (le chiavi più lunghe di B byte vengono prima cancellate usando H). Tuttavia, meno di L byte è fortemente scoraggiato in quanto ridurrebbe la sicurezza della funzione. Sono accettabili chiavi più lunghe di L byte, ma la lunghezza extra non aumenterebbe in modo significativo la forza della funzione. (Una chiave più lunga può essere consigliabile se la casualità della chiave è considerata debole.)

Per tradurre in linguaggio normale, la dimensione della chiave segreta deve avere le stesse dimensioni dell'output. La chiave deve anche essere in bit. Ogni cifra in base64 rappresenta 6 bit. Quindi, se avessi una password di 50 caratteri, avresti una chiave segreta 50 x 6 = 300 bit. Se stai usando SHA256, allora avresti bisogno di una chiave a 256 bit ( sha256 usa 256 bit per definizione ). Quindi una password lunga 50 dovrebbe funzionare a meno che tu non preveda di utilizzare un algoritmo di hashing più grande di SHA256.

Ma poiché ogni bit aggiuntivo nella chiave viene sottoposto a hash, la sua dimensione non ridurrà drasticamente le prestazioni. Ma ti garantirebbe che hai abbastanza bit per funzioni hash più grandi. SHA-512 verrebbe coperto da un SECRET_KEY lungo 100 ( 50 x 6 = 600 bit> 512 bit ).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.