Demystify Flask app.secret_key

If app.secret_key not installed, Flask will not allow you to install or access the session dictionary.

That's all the flask user manual can say about this.

I am very new to web development and I have no idea how / why any security element works. I would like to understand what Flask does under the hood.

  • Why does Flask force us to set this secret_key property?
  • How does Flask use the secret_key property?
+93
python flask web
Mar 17 '14 at 19:47
source share
2 answers

Everything that requires encryption (to protect against hacking by intruders) requires the installation of a secret key. For Flask itself, this “anything” is a Session object, but other extensions can use the same secret.

secret_key is simply the value set for the SECRET_KEY configuration of SECRET_KEY , or you can set it directly.

The Sessions section of Quick Start provides useful tips on what server-side secret should be set.

Encryption is based on secrets; if you do not set a secret on the server side for encryption, everyone will be able to crack your encryption; it's like a password to your computer. The secret plus signature data is used to create a signature string, a hard-to-recreate value using a cryptographic hashing algorithm ; only if you have exactly the same secret and source data can you recreate this value by letting Flask detect if anything has been changed without permission. Since the secret is never included in the data that Flask sends to the client, the client cannot interfere with the session data and hopes to create a new valid signature.

Flask uses its itsdangerous library to do all the hard work; Sessions use itsdangerous.URLSafeTimedSerializer class with a configured JSON serializer.

+79
Mar 17 '14 at 19:49
source share

The answer below mainly refers to Signed Cookies, an implementation of the concept of sessions (used in web applications). Flask offers both standard (unsigned) cookies (via request.cookies and response.set_cookie() ) and signed cookies (via flask.session ). The answer consists of two parts: the first describes how a signed cookie is generated, and the second is presented in QA form, which addresses various aspects of the scheme. The syntax used in the examples is Python3, but the concepts apply to previous versions.

What is SECRET_KEY (or how to create a signed SECRET_KEY )?

Signing cookies is a preventative measure against cookie fraud. During the cookie signing process, SECRET_KEY used in the same way that salt is used to tangle the password before hashing it. Here's a (wildly) simplified description of the concept. The code in the examples is for illustration. Many of the steps have been skipped, and not all functions actually exist. The goal here is to give an understanding of the general idea, actual implementations will be a little more complicated. Also, keep in mind that Flask does most of this for you in the background. Thus, in addition to setting values ​​to your cookie (through the session API) and providing SECRET_KEY , not only SECRET_KEY override this yourself, but there is no need to:

Poor Man's Cookie Signature

Before sending a response to the browser:

(1) First set SECRET_KEY . It should be known only to the application and should remain relatively constant throughout the life cycle of the application, including through application restarts.

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

(2) create cookies

 >>> 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) to create a signature, add (or add) SECRET_KEY to the cookie byte string, and then generate a hash from this combination.

 # 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) Now put a signature on one end of the content field of the original 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 

and what is sent to the client.

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

After receiving cookies from the browser:

(5) When the browser returns this cookie back to the server, remove the signature from the content field of the cookie to get the original 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) Use the original cookie with the SECRET_KEY application to recalculate the signature using the same method as in step 3.

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

(7) Compare the calculated result with the signature previously put forward from the cookie just received. If they match, we know that the cookies were not corrupted. But even if only a place is added to the cookie, the signatures will not match.

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

(8) If they do not match, you can respond with any number of actions, register an event, cancel a cookie, issue a new one, redirect to the login page, etc.

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

Hash Based Message Authentication Code (HMAC)

The type of signature generated above, which requires a secret key to ensure the integrity of some content, is called cryptography as a message authentication code or MAC.

Earlier, I pointed out that the above example simplifies this concept and that you should not create your own signature. This is because the algorithm used to sign cookies in Flask is called HMAC and is a bit more complex than the one described above step by step. The general idea is the same, but for reasons beyond the scope of this discussion, a number of calculations are a little more complicated. If you are still interested in creating DIY, as is usually the case, there are several modules in Python that will help you get started :) here is the starting block:

 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 and hashlib documentation




"Demystification" SECRET_KEY :)

What is the “signature” in this context?

This is a way to ensure that any content has not been altered by anyone other than the person or organization authorized to do so.

One of the simplest forms of signature is a “ checksum, ” which simply confirms that the two pieces of data are the same. For example, when installing software from source code, it is important to first confirm that your copy of the source code is identical to the original one. The usual approach for this is to run the source code using a cryptographic hash function and compare the output with the checksum published on the project home page.

Suppose, for example, that you are going to download the project source code in a compressed file from a web mirror. The SHA1 checksum published on the project web page is called '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.... 

Both hashes are the same, you know that you have an identical copy.

What kind of cookie?

A detailed discussion of cookies is beyond the scope of this issue. I’ll give an overview here, as a minimal understanding may be useful to better understand how and why SECRET_KEY is useful. I highly recommend that you read some of the personal articles about HTTP cookies.

A common practice in web applications is to use a client (web browser) as a lightweight cache. Cookies are one of the implementations of this practice. A cookie is usually some data added by a server to an HTTP response through its headers. It is saved by the browser, which subsequently sends it back to the server when issuing requests, including through HTTP headers. The data contained in the cookie can be used to simulate what is called statefulness, the illusion that the server maintains a constant connection with the client. Only in this case, instead of a wire to maintain a “live” connection, you just get snapshots of the state of the application after it processed the client’s request. These snapshots are transferred between the client and server. Upon receiving the request, the server first reads the contents of the cookie to restore the context of its dialogue with the client. It then processes the request in this context and, before returning the response to the client, updates the cookie. The illusion of an ongoing session is thus preserved.

What does a cookie look like?

A typical cookie would look like this:

 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 

Cookies are trivial to view in any modern browser. For example, in Firefox, go to "Settings"> "Privacy"> "History"> "Delete individual cookies."

The content field is most relevant to the application. Other fields contain mostly meta instructions for defining various areas of influence.

Why use cookies at all?

The short answer is performance. The use of cookies minimizes the need to search for objects in various data stores (cache, files, databases, etc.), thereby speeding up the process on the server application side. Keep in mind that the larger the cookie, the greater the load on the network, so what you save in the database search on the server can be lost on the network. Think carefully about what to include in your cookies.

Why should cookies be signed?

Cookies are used to store all kinds of information, some of which can be very confidential. They are also inherently unsafe and require that a number of additional precautions be taken to be considered safe in any case for both parties, the client and the server. Signing cookies specifically solves the problem that they may be associated with when trying to trick server applications. There are other measures to mitigate other types of vulnerabilities, so I recommend that you learn more about cookies.

How can I change the cookie?

Cookies are located on the client in text form and can be easily edited. The cookie received by your server application may have been altered for several reasons, some of which may be innocent. Imagine a web application that stores information about the permissions of its users in cookies and provides privileges based on this information. If cookies are not protected against unauthorized access, anyone can change them to upgrade their status from "role = visitor" to "role = admin", and the application will not be wise.

Why SECRET_KEY need to sign cookies?

Checking cookies is a little different than checking source code, as described earlier. In the case of the source code, the original author is the trustee and owner of the reference fingerprint (checksum), which will be stored in the public domain. You do not trust the source code, but trust the public signature. So in order to check your copy of the source, you just want your computed hash to match the public hash.

However, in the case of a cookie, the application does not track the signature; it tracks its SECRET_KEY . SECRET_KEY is a reference fingerprint. Cookies travel with a signature that they consider legal. The legitimacy here means that the signature was issued by the owner of the cookie, that is, the application, in which case it is a statement that you do not trust, and you need to check the signature for authenticity. To do this, you need to include in the signature only the SECRET_KEY known to you - SECRET_KEY . Someone may modify the cookie, but since it does not have a secret component to correctly calculate the valid signature, it cannot fake it. As mentioned earlier, this type of fingerprinting, where in addition to the checksum is also provided with a secret key, is called the message authentication code.

What about sessions?

Sessions in their classic implementation are cookies that contain only an identifier in the content session_id field. The purpose of the sessions is exactly the same as for signed cookies, i.e. to prevent cookie fraud. Classic sessions have a different approach though. After receiving a session cookie, the server uses the identifier to search for session data in its own local storage, which may be a database, a file, or sometimes a cache in memory. A session cookie is usually set for the expiration date when you close your browser. Due to the search step in local storage, such a session implementation usually causes performance degradation. Signed cookies are becoming the preferred alternative, and thus Flask sessions are implemented. In other words, Flask sessions are signed cookies, and to use signed cookies in Flask just use its Session API.

Why not encrypt cookies?

Sometimes the contents of cookies may be encrypted before being signed. This is done if they are considered too sensitive to be visible from the browser (encryption hides the content). However, the simple signature of cookies solves another problem when it is necessary to maintain the visibility and usability of cookies in the browser, preventing them from being tampered with.

What happens if I change SECRET_KEY ?

By changing SECRET_KEY you SECRET_KEY force all cookies signed by the previous key. When the application receives a request with a cookie that was signed using the previous SECRET_KEY , it will try to calculate the signature with the new SECRET_KEY and both signatures will not match, this cookie and all its data will be rejected, it will be as if the browser is connecting to the server for the first time. Users will be logged out and their old cookie will be forgotten along with everything that is stored inside. Please note that this is different from the method of processing expired cookies. An expired cookie can be extended if its signature is verified. Invalid signature means only invalid cookie.

Therefore, if you do not want to cancel all signed cookies, try to keep SECRET_KEY same for extended periods.

What a good SECRET_KEY ?

The secret key must be hard to guess. The session documentation has a good recipe for generating random keys:

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

You copy the key and paste it into your configuration file as the value of SECRET_KEY .

If you do not use a randomly generated key, you can use a complex set of words, numbers and symbols, possibly located in a sentence known only to you, encoded in byte form.

Do not set SECRET_KEY directly with a function that generates a new key each time it is called. For example, do not do this:

 # this is not good SECRET_KEY = random_key_generator() 

Each time your application restarts, it is given a new key, which makes the previous one invalid.

Instead, open the python interactive shell and call the function to generate the key, then copy and paste it into the configuration.

+47
Feb 03 '18 at 11:29
source share



All Articles