Obviously I have a problem to understand the impact of Django (2.2.4) settings regarding CSRF parameters in a cross-domain environment.
As I have already noticed I have to set SESSION_COOKIE_SAMESITE = None if I want to place my Django application into an iframe of a website with another domain (e.g. Django app on foo.com and iframe on bar.com) in order to send forms on my Django application.
However what's about the CSRF parameters? After some trials I noticed that I can only send the Django form in the iframe if I also set CSRF_COOKIE_SAMESITE = Nonein the Django settings.
But what is the CSRF_TRUSTED_ORIGINS for? If I set the iframe domain (e.g. bar.com) into the list ['bar.com'] instead of CSRF_COOKIE_SAMESITE = None I can not send the form on my Django app in the iframe.
Could anybody explain in what case CSRF_TRUSTED_ORIGINS has any effect? Is it just usable in an environment with one domain and serveral subdomains?
Thanks for any hint!
Briefly: CSRF_COOKIE_SAMESITE affects browser behavior, while CSRF_TRUSTED_ORIGINS affects Django's behavior. You will need to make sure both are set appropriately.
The CSRF_COOKIE_SAMESITE setting simply determines what SameSite directive, if any, is used for the CSRF SetCookie. That directive will then be used by the browser to determine whether or not to include the cookie in a request.
The CSRF_TRUSTED_ORIGINS setting is there to allow you to make exceptions to Django's default behavior of strictly checking the Host and Referer headers on incoming requests with CSRF protection. See the documentation for more on this check.
So, when you didn't set CSRF_COOKIE_SAMESITE to None, Django used its default value of 'Lax', which instructed the browser not to send the cookie cross-domain with unsafe requests (like POST). Since the cookie wasn't sent, CSRF_TRUSTED_ORIGINS was irrelevant.
Related
CSRF_COOKIE_SAMESITE = 'None'
CSRF_COOKIE_SECURE = False
My frontend and backend run on different domains in development, I'm trying to enable setting csrf-token cookie using HTTP, but I guess False value for CSRF_COOKIE_SECURE option somehow gets interpreted as 'not set' and Chrome says
My second guess is that it has to be True, otherwise it's not allowed to send cookies between domains. So my question is whether it's possible to set cookies via plain HTTP with cross-domain requests and if it is, what are the right Django settings for achieving this
As the title suggests, I don’t think this is possible in Django:latest as of the time if writing, but is it possible to detect if a cookie sent up in the request.HEADERS is httpOnly?
For instances, you can use OWASP ZAP or Detectify to check if the cookies are being set without the HttpOnly flag.
Don't you also forget that in Django, there's settings you can take advantage of by setting to True in your settings.py, for instances
LANGUAGE_COOKIE_HTTPONLY
SESSION_COOKIE_HTTPONLY
CSRF_COOKIE_HTTPONLY
No. HttpOnly is a directive of the Set-Cookie response header. There is nothing in the Cookie request header that indicates that. This is a fact about HTTP and not a limitation of Django.
So I am trying to deploy my site and basically tried
python manage.py check --deploy
and followed what ever it told me:
WARNINGS:
?: (security.W004) You have not set a value for the SECURE_HSTS_SECONDS setting. If your entire site is served only over SSL, you may want to consider setting a value and enabling HTTP Strict Transport Security. Be sure to read the documentation first; enabling HSTS carelessly can cause serious, irreversible problems.
?: (security.W006) Your SECURE_CONTENT_TYPE_NOSNIFF setting is not set to True, so your pages will not be served with an 'x-content-type-options: nosniff' header. You should consider enabling this header to prevent the browser from identifying content types incorrectly.
?: (security.W007) Your SECURE_BROWSER_XSS_FILTER setting is not set to True, so your pages will not be served with an 'x-xss-protection: 1; mode=block' header. You should consider enabling this header to activate the browser's XSS filtering and help prevent XSS attacks.
?: (security.W008) Your SECURE_SSL_REDIRECT setting is not set to True. Unless your site should be available over both SSL and non-SSL connections, you may want to either set this setting True or configure a load balancer or reverse-proxy server to redirect all connections to HTTPS.
?: (security.W012) SESSION_COOKIE_SECURE is not set to True. Using a secure-only session cookie makes it more difficult for network traffic sniffers to hijack user sessions.
?: (security.W016) You have 'django.middleware.csrf.CsrfViewMiddleware' in your MIDDLEWARE, but you have not set CSRF_COOKIE_SECURE to True. Using a secure-only CSRF cookie makes it more difficult for network traffic sniffers to steal the CSRF token.
?: (security.W017) You have 'django.middleware.csrf.CsrfViewMiddleware' in your MIDDLEWARE, but you have not set CSRF_COOKIE_HTTPONLY to True. Using an HttpOnly CSRF cookie makes it more difficult for cross-site scripting attacks to steal the CSRF token.
?: (security.W018) You should not have DEBUG set to True in deployment.
?: (security.W019) You have 'django.middleware.clickjacking.XFrameOptionsMiddleware' in your MIDDLEWARE, but X_FRAME_OPTIONS is not set to 'DENY'. The default is 'SAMEORIGIN', but unless there is a good reason for your site to serve other parts of itself in a frame, you should change it to 'DENY'.
?: (security.W020) ALLOWED_HOSTS must not be empty in deployment.
Basically setting all those to True in settings.py and set Debug mode to False, and put SECURE_HSTS_SECONDS = 300
However, I forgot to set up my site on a server before doing this and now when I tried to access it, it gives me this error in browser:
Secure Connection Failed
An error occurred during a connection to 127.0.0.1:8001. SSL received a record that exceeded the maximum permissible length. Error code: SSL_ERROR_RX_RECORD_TOO_LONG
The page you are trying to view cannot be shown because the authenticity of the received data could not be verified.
Please contact the website owners to inform them of this problem.
and those in cmd:
[14/Sep/2016 17:40:46] code 400, message Bad request syntax ('\x16\x03\x01\x00|\x01\x00\x00x\x03\x02\xd3\xb8S<\t¿°\xfd½U»ïä\x98\x99h\xb9¥±T~\x129\x05á\xc0V\t\x9a\xe3\x82E\x00\x00\x10\xc0\t\xc0\x13\xc0')
[14/Sep/2016 17:40:46] You're accessing the development server over HTTPS, but it only supports HTTP.
Okay so it clearly tell me the problem: I am not supporting HTTPs but the setting is set to support it. But the weird thing is even after I delete all those settings, the site stays this way and I just can't even access it in development with DEBUG = True.
I even tried to use git to revert to the version before I did this, and it doesn't help. The same error remains. Now I am really worried that maybe I just destroyed it? Please somebody help me
Have you tried a different browser to access your (dev) website? Maybe its because of the value you gave on the setting SECURE_HSTS_SECONDS. If this is too high (say 31536000 == 1 year) the browser will keep hitting the https version of your site.
However, you can clear the browser's HSTS setting. Maybe this can help.
For a better understanding of HSTS (if this is the issue) read this article.
Let me know if this helped you.
We have a django app accessed via SSL (i.e. with https). When we went
to the admin site and it was redirected to admin/login/?next=/admin/
because we were not logged in, the https was not carried over and the
request failed. I added
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
to my settings and then the admin redirect worked. But we have some
clients that access the site with curl or python requests and after
adding that all their existing code broke. They now all have to add a
referer to all their requests for them to work.
My question is, is there a way to make the admin redirect work but not
require all the other requests to have a referer? A non redirected
request from the browser works, and that doesn't have a referer, so
why is it required on the curl requests?
I found this:
https://code.djangoproject.com/ticket/16870
which I guess somewhat answers my question.
I have a public Django site which uses CSRF protection.
I have not set the CSRF_COOKIE_DOMAIN. My site uses subdomains.
Sometimes, a user ends up having a csrftoken cookie set on .toplevel.com as well as on sub.toplevel.com. This causes problems, as CSRF checking fails if the wrong cookie is used in the check.
I would like to set a CSRF_COOKIE_DOMAIN to .toplevel.com. However, I would also like to delete any csrftoken cookies for any *.toplevel.com subdomains. How would I do this?
If I do not delete the other cookies, I will just end up in the original situation of having two cookies with the same name on different domains, which causes issues.
I had a similar problem. The way I dealt with it is together with CSRF_COOKIE_DOMAIN I also changed the CSRF_COOKIE_NAME, making old "csrftoken" cookies obsolete.