It is always better for security, though not always practical in all cases, to deploy your site behind HTTPS. Without this, it is possible for malicious network users to sniff authentication credentials or any other information transferred between client and server, and in some cases – active network attackers – to alter data that is sent in either direction.
If you want the protection that HTTPS provides, and have enabled it on your server, there are some additional steps you may need:
- If necessary, set
SECURE_PROXY_SSL_HEADER, ensuring that you have understood the warnings there thoroughly. Failure to do this can result in CSRF vulnerabilities, and failure to do it correctly can also be dangerous!
- Set up redirection so that requests over HTTP are redirected to HTTPS.This could be done using a custom middleware. Please note the caveats under
SECURE_PROXY_SSL_HEADER. For the case of a reverse proxy, it may be easier or more secure to configure the main Web server to do the redirect to HTTPS.
- Use “secure” cookies. If a browser connects initially via HTTP, which is the default for most browsers, it is possible for existing cookies to be leaked. For this reason, you should set your
True. This instructs the browser to only send these cookies over HTTPS connections. Note that this will mean that sessions will not work over HTTP, and the CSRF protection will prevent any
POSTdata being accepted over HTTP (which will be fine if you are redirecting all HTTP traffic to HTTPS).
- Use HTTP Strict Transport Security (HSTS). HSTS is an HTTP header that informs a browser that all future connections to a particular site should always use HTTPS (see below). Combined with redirecting requests over HTTP to HTTPS, this will ensure that connections always enjoy the added security of SSL provided one successful connection has occurred. HSTS is usually configured on the web server.
HTTP Strict Transport Security
For sites that should only be accessed over HTTPS, you can instruct modern browsers to refuse to connect to your domain name via an insecure connection (for a given period of time) by setting the Strict-Transport-Security header. This reduces your exposure to some SSL-stripping man-in-the-middle (MITM) attacks.
SecurityMiddleware will set this header for you on all HTTPS responses if you set the
SECURE_HSTS_SECONDS setting to a non-zero integer value.
When enabling HSTS, it’s a good idea to first use a small value for testing, for example,
SECURE_HSTS_SECONDS = 3600 for one hour. Each time a Web browser sees the HSTS header from your site, it will refuse to communicate non-securely (using HTTP) with your domain for the given period of time.
Once you confirm that all assets are served securely on your site (i.e. HSTS didn’t break anything), it’s a good idea to increase this value so that infrequent visitors will be protected (31536000 seconds, i.e. 1 year, is common).
Additionally, if you set the
SECURE_HSTS_INCLUDE_SUBDOMAINS setting to
SecurityMiddleware will add the
includeSubDomains tag to the
Strict-Transport-Security header. This is recommended (assuming all subdomains are served exclusively using HTTPS), otherwise your site may still be vulnerable via an insecure connection to a subdomain.
Host Header Validation
Django uses the
Host header provided by the client to construct URLs in certain cases. While these values are sanitized to prevent Cross Site Scripting attacks, a fake
Host value can be used for Cross-Site Request Forgery, cache poisoning attacks, and poisoning links in emails.
Because even seemingly-secure Web server configurations are susceptible to fake
Host headers, Django validates
Host headers against the
ALLOWED_HOSTS setting in the
This validation only applies via
get_host(); if your code accesses the
Host header directly from
request.META you are bypassing this security protection.
Similar to the CSRF limitations requiring a site to be deployed such that untrusted users don’t have access to any subdomains,
django.contrib.sessions also has limitations. See the session topic guide section on security for details.
- If your site accepts file uploads, it is strongly advised that you limit these uploads in your Web server configuration to a reasonable size in order to prevent denial of service (DOS) attacks. In Apache, this can be easily set using the
- If you are serving your own static files, be sure that handlers like Apache’s
mod_php, which would execute static files as code, are disabled. You don’t want users to be able to execute arbitrary code by uploading and requesting a specially crafted file.
- Django’s media upload handling poses some vulnerabilities when that media is served in ways that do not follow security best practices. Specifically, an HTML file can be uploaded as an image if that file contains a valid PNG header followed by malicious HTML. This file will pass verification of the library that Django uses for
ImageFieldimage processing (Pillow). When this file is subsequently displayed to a user, it may be displayed as HTML depending on the type and configuration of your web server.No bulletproof technical solution exists at the framework level to safely validate all user uploaded file content, however, there are some other steps you can take to mitigate these attacks:
- One class of attacks can be prevented by always serving user uploaded content from a distinct top-level or second-level domain. This prevents any exploit blocked by same-origin policy protections such as cross site scripting. For example, if your site runs on example.com, you would want to serve uploaded content (the MEDIA_URL setting) from something like usercontent-example.com. It’s not sufficient to serve content from a subdomain like usercontent.example.com.
- Beyond this, applications may choose to define a whitelist of allowable file extensions for user uploaded files and configure the web server to only serve such files.