Securing your Django app
from man-in-the-middle attacks
Ventsislav Tashev
👨💻 Software Developer @ HackSoft
👨🏼🎓 Studying Informatics @ NBU
❤️ Python & Django
Man-in-the-middle (MITM)
domain.com
http://domain.com
http://domain.com
HTTP 200
domain.com
http://domain.com
http://domain.com
HTTP 200
domain.com
http://domain.com
http://domain.com
HTTP 200
HTTP HTTPS
301 Moved Permanently
# settings.py
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = True
domain.com
http://domain.com
https://domain.com
HTTP 301
domain.com
http://domain.com
https://domain.com
HTTP 301
301 is not enough.
- The redirect happens once the HTTP request reaches the server. The MITM attacker enters before that.
301 is not enough.
- The redirect happens once the HTTP request reaches the server. The MITM attacker enters before that.
- Even if the browser is caches this redirect, it has a max-age of several weeks/months.
301 is not enough.
- The redirect happens once the HTTP request reaches the server. The MITM attacker enters before that.
- Even if the browser is caches this redirect, it has a max-age of several weeks/months.
- We all know the common fix for the "the site is not working" is "reset your browser cache". This automatically re-exposes the user for the MITM threat.
301 is not enough.
HSTS
HTTP Strict Transport Security
HTTP Strict Transport Security, or HSTS, is a way of telling the browser to load your site over HTTPS only.
HTTP Strict Transport Security, or HSTS, is a way of telling the browser to load your site over HTTPS only.
Once a browser has seen the header on a website, it will only make HTTPS requests to that website.
HSTS directives
HSTS directives
- max-age instructs the browser how long it should load your domain with encrypted connection (in seconds).
HSTS directives
- max-age instructs the browser how long it should load your domain with encrypted connection (in seconds).
- includeSubDomains includes all subdomains of your domain.
HSTS directives
- max-age instructs the browser how long it should load your domain with encrypted connection (in seconds).
- includeSubDomains includes all subdomains of your domain.
- preload tells browsers to store your domain in a database of known strict-only domains. It can only be set on top level domains like example.com. Browsers opening URL’s on HSTS-preloaded domains will never make MITM-able HTTP requests. Once this flag is set, you submit your domain to all browsers through Google’s preload service. After acceptance, the next versions of each browser will include your domain.
Django’s warning security.W004 even says:
… enabling HSTS carelessly can cause serious, irreversible problems
Django’s warning security.W004 even says:
… enabling HSTS carelessly can cause serious, irreversible problems
- If you prematurely activate it, you will block users making legitimate HTTP requests. The browser will lock them out until you remove the header and the max-age seconds have passed.
# settings.py
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = True
SECURE_HSTS_SECONDS = 31536000 # 1 year
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
domain.com
https://domain.com
HTTP 200
Check HSTS registry for domain.com
http(s)://domain.com
Flow
- User types domain.com in the browser
- Browser checks its HSTS registry to check whether the domain is present there:
- If it is found -> resolve to https
- Otherwise -> fallback to http
- Once the schema is determined -> perform the request
- The request hits the Django web server:
- If the request is non-encrypted (http) -> HTTP 301
- If the request is encrypted (https) -> HTTP 200
-
Return response to the client
- If Strict-Transport-Security header is present in the response - cache the domain in the HSTS registry
Comparison
HSTS | 301 Redirect |
---|
Comparison
HSTS | 301 Redirect | |
---|---|---|
Designed for | Security | URL Redirection |
Comparison
HSTS | 301 Redirect | |
---|---|---|
Designed for | Security | URL Redirection |
Covers | The entire domain | A specific URL |
Comparison
HSTS | 301 Redirect | |
---|---|---|
Designed for | Security | URL Redirection |
Covers | The entire domain | A specific URL |
Cache | Separate | Browser |
Comparison
HSTS | 301 Redirect | |
---|---|---|
Designed for | Security | URL Redirection |
Covers | The entire domain | A specific URL |
Cache | Separate | Browser |
Max-age | Years | Weeks/months |
HSTS is not perfect.
HSTS is not perfect.
-
If the domain is not present in the HSTS registry, a single HTTP request should be made in order to cache the domain in order to perform HTTPS-only requests in the future.
HSTS is not perfect.
-
If the domain is not present in the HSTS registry, a single HTTP request should be made in order to cache the domain in order to perform HTTPS-only requests in the future.
-
HTTPS requests can still be decrypted by the attacker, but he needs to be a lot more sophisticated in order to achieve that.
HSTS is not perfect.
HSTS is not perfect.
But it is a big security improvement!
Resources
Django MITM
By Ventsislav Tashev
Django MITM
How to prevent man-in-the-middle attacks in your Django application
- 933