Understanding the Security of Django SECRET_KEY
I am nearing a point where I will deploy my Django application to the hostile environment otherwise known as “the internet” and I’m trying to better understand the ramifications of the Django SECRET_KEY
. One of the standard procedures it seems is to secure the secret key in the settings.py
. Fair enough. The docs go so far to say to not commit your secret key to SVN, CVS, etc… For this provides easy access to your key. However, if anyone were tempted to commit the secret key to their repo, this would indicate that the secret key is static (see question #4)?
Anyway, here are my questions:
- How is storing the secret key as an environment variable any more secure than storing it directly in
settings.py
? For example, if an attacker can readsettings.py
, he more than likely can just type$ echo $DJANGO_SECRET_KEY
! - How is storing the secret key in a file any more secure than storing it directly in
settings.py
? If he can readsettings.py
, he probably can readdjango_secret_key.txt
. - If the attacker has compromised your machine, can’t they simply load the python interpreter with
settings.py
to> print settings.SECRET_KEY
? - Finally, would it be a bad practice to randomly generate the secret key each time the webserver process is restarted? This could be completely random, or it could prompt for user input for the key. Obviously, the latter presents a serious weakness if the attacker himself can restart the webservice and input the key of his choice.
Answer
Once an attacker already has access to the system it’s already way too late. The main concern for not leaking the key is because it is often used as a seed for hashing and signing sessions. The idea is that your production SECRET_KEY
needs to be completely different than your development or staging SECRET_KEY
. You can actually randomly generate it every restart although this might impact user experience (see details below).
As long as you adhere to the principle of changing the key there is not much danger if you commit or not (as long as you ensure it is changed once going from dev to prod). If you don’t, then someone having the key can predict the outcome of hashing algorithms (used for sessions) or even sign sessions.
If an attacker has gained access to your system you’re already too far gone because it’s not your system anymore. One thing you do need to ensure is that the file permissions on your settings file is only readable by the user running the webserver and by no-one else. This prevents someone who illegitemately gained access to a limited account, which is not the same as the webserver account, from compromising your key.
There is a good answer here on Stack Overflow: Django SECRET_KEY written by sberder which details what it is used for:
- JSON object signing
- crypto functions for salted hmacs or seeding the random engine which impacts:
- password reset token
- comment form security to protect against forged POST requests
- form security
- protect against message tampering as the message framework may use cookies to pass messages between views.
- protect session data and create random session keys to avoid tampering as well.
- create random salt for most password hashers
- create random passwords if necessary
- create itself when using
startproject
- create CSRF key
In reality a lot of the items listed here use
SECRET_KEY
throughdjango.utils.crypt.get_random_string()
which uses it to seed the random engine. This won’t be impacted by a change in value ofSECRET_KEY
.User experience directly impacted by a change of value are:
- sessions, the data decode will break, that is valid for any session backend (cookies, database, file based or cache).
- password reset token already sent won’t work, users will have to ask a new one.
- comments form (if using
django.contrib.comments
) will not validate if it was requested before the value change and submitted after the value change. I think this is very minor but might be confusing for the user.- messages (from
django.contrib.messages
) won’t validate server-side in the same timing conditions as for comments form.