# Insecure Cookies
Stateful browsing is generally implement by web-servers using cookies. There are several key aspects to securing your cookies:
* You should prevent cookies being read from client-side JavaScript, to avoid the possible of cookie theft via **cross-site scripting**.
* To avoid cookie-hijacking via **man-in-the-middle** attacks, it is important to only send cookies over HTTPS connections.
* If you store session IDs in cookies, you should generate those IDs from a strong random number algorithm to avoid **brute-forcing** of session identifiers.
* If you store session state in a cookie, you should be able to detect when a malicious user tampers with the cookie contents by using **digital signatures** – and you should avoid storing sensitive data in the session.
## Cookie Theft via Cross-Site Scripting (XSS)
If cookies can be accessed by JavaScript in the browser, hackers will try to smuggle malicious JavaScript into your web pages so they can steal cookies from your users. You can protect against this type of attack by adding the `HttpOnly` attribute to your cookies, instructing the browser to make them inaccessible to client-side JavaScript code.
There’s rarely a good reason to access cookies in the browser, so this approach comes with no cost. For example, here is how you configure a Flask web-server to make the session cookie inaccessible to JavaScript:
“`python from flask import Flaskapp = Flask(__name__) # In Flask, the session cookie is HTTP-only by default, so this is redundant. |
## Cookie Theft via Man-in-the-Middle Attacks
If cookies are passed over an insecure connection, attackers will attempt to snoop on your web traffic in order to steal them. You can protect against this type of attack by adding the `Secure` attribute to your cookies, instructing the browser to only send cookies over HTTPS. Here’s how to do that with the Flask web-server:
“`python from flask import Flaskapp = Flask(__name__) # Ensure the cookie is only passed over HTTPS. You probably want to make this setting |
## Further Considerations
### Adding the `Strict-Transport-Security` Header
It is best practice to serve all of your content over HTTPS. If you do this, you can tell the browser to always ask for a secure connection by adding the `Strict-Transport-Security` header to your HTTP responses.
In Flask you can add this header to all responses in the following manner:
“`python from flask import Flaskapp = Flask(__name__) @app.after_request |
### Session ID Generation
If your web-server keeps session state on the server-side, it will generate a session ID to pass in the session cookie. This session ID needs to securely random and unguessable. Here’s how the `Flask-sessions` extension generates secure session IDs:
“`python class SessionInterface(FlaskSessionInterface): def _generate_sid(self): return str(uuid4()) “` |
### Signing Sessions
If your web-server stores session state in the session cookie, it will need to add a digital signature to the cookie to ensure it is not tampered with. Here is the signing algorithm used by the Flask web-server;
“`python def sign(self, value: _t_str_bytes) -> bytes: “””Signs the given string and also attaches time information.””” value = want_bytes(value) timestamp = base64_encode(int_to_bytes(self.get_timestamp())) sep = want_bytes(self.sep) value = value + sep + timestampreturn value + sep + self.get_signature(value) “` |
## CWEs
* [CWE-1004](https://cwe.mitre.org/data/definitions/1004.html)
* [CWE-614](https://cwe.mitre.org/data/definitions/614.html)