Django (Python) problem with sessionid - python

I am having a problem with sessionid: request.session.session_key Generates a key every page refresh / form submission.
While this: request.COOKIES[settings.SESSION_COOKIE_NAME] complains that 'sessionid' key is not found.
Am I missing something? I need a "key" that is persistent across page requests on my site. I need it to persist even when the browser is closed/3 weeks, etc. How would I do this is Django?
Do I need to configure something? If I am misunderstanding something regarding the sessionid and how it is generated, please correct me.
Thanks for your replies.
Regards,
W
My settings.py is: http://pastebin.com/G9qnD9En

It sounds like your browser is not accepting the session cookies that Django is sending.
Your browser should be able to tell you what cookies are being set with a page response from your application. Check to see that a 'sessionid' cookie is actually being sent, and that the domain and path are correct.
If you have SESSION_COOKIE_DOMAIN or SESSION_COOKIE_PATH set incorrectly in your settings.py file, they may be causing Django to set cookies in the browser that are not being returned to the server.
If you want to verify your whole setup, start by reading this: http://docs.djangoproject.com/en/1.2/topics/http/sessions/
In a nutshell, you need to:
have 'django.contrib.sessions' in your INSTALLED_APPS;
have 'django.contrib.sessions.middleware.SessionMiddleware' in MIDDLEWARE_CLASSES; and
on a production server, you may need to set SESSION_COOKIE_DOMAIN and SESSION_COOKIE_PATH to interact well with other web applications on the same domain or related domains.
Edit:
Having looked at your pasted settings, I can see that there are two different things going on, each of which is enough to stop the session cookies from working.
SESSION_COOKIE_DOMAIN is set to "mydomain.com"
A cookie for a generic TLD requires that the "domain" part contain at least two period (".") separators in it. This stops people from setting cookies for domains like ".com". (Cookies for domains under country-level jurisdiction, I believe, require three periods.)
Change this to ".mydomain.com" and it should be returned by the browser.
In development (running on your local machine, at 127.0.0.1), leave this setting blank, or your browser won't accept the cookie at all.
SESSION_COOKIE_PATH is set to "/tmp"
This looks like a mistake, unless your web application is hosted at "http://mydomain.com/tmp/"
SESSION_COOKIE_PATH is used to indicate the "path" component of the cookie, i.e., the URL prefix under which the cookie will be returned to the server. This lets you host one application at "mydomain.com/firstapp/" and another at "mydomain.com/secondapp/", and you can be sure that the "sessionid" cookies will not be confused between them.
If you only have one application hosted under this domain name, then leave it blank, and it will default to "/" (the entire domain)
To control where Django stores session data on your filesystem (which is what it looks like you're trying to do), you can use the SESSION_FILE_PATH setting. By default, it is set to "/tmp/" anyway, so you shouldn't need to set it at all.

I had a similar problem, and I fixed it by setting SESSION_COOKIE_NAME to something other than the default 'sessionid'. I think google analytics might have been clobbering the cookie somehow.

Related

How would changing Django's cookie domain settings cause sporadic CSRF failures?

In my Django project, until recently I had left the settings SESSION_COOKIE_DOMAIN and CSRF_COOKIE_DOMAIN unset. Recently I changed them to .mydomain.com and since then I have been seeing sporadic CSRF failures on AJAX requests for certain users. The failure manifests as a 403 with CSRF token missing or incorrect. appearing in the logs.
Asking users to clear cookies seems to resolve the issue, but I'm wondering how the settings change could have caused this and why it only seems to be happening for some users and not others.
Wondering if there is a way to resolve these issues without asking my users to clear cookies.
The cookie with the new SESSION_COOKIE_DOMAIN is sent as a new cookie and does not replace the old one. So the browser will send both to your server. AFAICT, it sends them in arbitrary order.
That means that you're setting a cookie for .mydomain.com, but receiving either the cookie you just set for .mydomain.com, or a stale cookie for whatever.mydomain.com was implicitly set originally (because django will only pick one, most likely the last it sees). Which one you get depends on the browser, possibly on some particulars of how the client computer stores them, and possibly even on how django reads the headers. This is why the failures are inconsistent: it randomly works for some clients and fails for others.
Edit: You could delete the stale cookie from the server, if you know the original cookie's properties. Probably the best way is to set a custom Set-Cookie header with the domain and other properties set, and expiration date in the past. You could do that e.g. from the 403 page handler.
(see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie and Correct way to delete cookies server-side )

Flask sessions, where are the cookies stored?

I'm learning flask and want to understand how sessions work.
Apparently the server stores a signed cookie on the client browser.
I have done this process using
sessions['mycookie'] = 'mycookievalue'
But I'm unable to find the cookie on the browser. I normally list cookies on the browser using chrome developer tools and running the command:
document.cookie
This works when I set a cookie but nothing comes up when I set it through sessions.
The Flask session cookie has the httponly flag set, making it invisible from JavaScript.
It is otherwise a normal, regular cookie so it is still stored in the browser cookie store; you should still be able to see it in your browser's developer tools.
You can set the SESSION_COOKIE_HTTPONLY option to False if you want to be able to access the cookie value from JavaScript code. From the Builtin Configuration Values section:
SESSION_COOKIE_HTTPONLY
controls if the cookie should be set with the httponly flag. Defaults to True.
The cookie contains all your session data, serialised using JSON (with tagging support for a wider range of Python types), together with a cryptographic signature that makes sure the data can't be tampered with securely.
If you disable the httponly protection, any JS code could still decode and read all your session data. Even if it can't change those values, that could still be very interesting to malicious code. Imagine a XSS bug in your site being made worse because the JS code could just read a CSRF token used to protect a web form straight from the session.
I am finding this question 3 years and 8 months later because I have an interest in the event it is modified or spoofed, to ensure my backend is able to tell the difference.
Using chrome, use F12, select Application tab, underneath Storage go to Cookies. Under cookies you'll find the webpage, select it and the right side will populate and assuming you have done something to create your session cookie, it will be there. You will notice that the value is encrypted.
Picture showing the location of session cookie
sessions are meant for server use only. That is why it is hidden and encrypted for the client.
If you want to set a cookie which can be used by client/browser. You can just set a normal cookie instead of a secure cookie (like session).
You can set cookies by modifying response.
def home_page():
resp = make_response(...)
resp.set_cookie('my_cookie', 'cookie_value')
return resp
document.cookie on browser will give you mycookie=cookie_value

Django session id security tips?

I'm currently developing a site with Python + Django and making the login I started using the request.session[""] variables for the session the user was currently in, and i recently realized that when i do that it generates a cookie with the "sessionid" in it with a value every time the user logs in, something like this "c1cab412bc71e4xxxx1743344b3edbcc" and if I take that string and paste it in the cookie on other computer in other network and everything, i can have acces to the session without login in.
So what i'm asking here actually is if anyone can give me any tips of how can i add some security on my system or if i'm doing something wrong setting session variables?
Can anyone give me any suggestions please?
Sadly, there is no best way you can prevent this from what I know but you can send the owner of an account an email and set some type of 2fa.
There are a couple of things that can do to help improve the security on session cookies.
You can force a session to expire as soon as the user closes their browser.
In your settings.py file add:
SESSION_EXPIRE_AT_BROWSER_CLOSE=True
You can manually set the number of seconds until a session expires
Using the first argument(request) of any view:
request.session.set_expiry(value) # number of seconds or timedelta object
To address your specific issue, please consider that what you are describing is actually one of the primary features of session security cookies. They are convenience tools that enable users to use the secured parts of site without having to re-authenticate with every page request. Even the cross browser aspect of it is a feature since many apps and browsers provide a sync feature that allows you to share cookies and sessions datas with your mobile and other devices and other web browsers.
If you still feel that this is too significant of a security risk, then probably the safest approach would be to remove the SessionMiddleware
from MIDDLEWARE and django.contrib.sessions both in your settings.py

Django remote user authentication and security

I am using Django remote user authentication in a project. What I am actually using is just django.contrib.auth.RemoteUserBackend without the middleware, and manually calling authenticate after having checked with the backend that the user is legitimate.
Reading the source of the middleware, it seems that it just takes the username from a header in the request and then authenticates the user against the backend passing this username. The remote user backend, in turn, just merrily logs the user in with whatever username was passed. The user has then access to every area that requires a valid login.
Isn't this just a huge security flaw? How is this meant to be used?
In my case I should be safe, since the only call to authenticate comes after a successful remote identity verification, but I am wondering the reason why the middleware was introduced.
Let me turn this around on you: if you think this is a security flaw, then try writing an exploit that sets the REMOTE_USER header in a request to your app and see what happens.
REMOTE_USER dates back to the early days of the web when CGI pages were executed locally as the user you were hitting the web page with. REMOTE_USER is actually the name of a unix environment variable that denotes the active user. As security models for web servers changed, this scheme was preserved for compatibility. Now even IIS supports it to transparently handle Active Directory logins.
All user-passed headers begin with HTTP_. Otherwise, you couldn't trust on any header information, like SERVER_NAME, which would be an enormous mess.
Django 'merrily logs the user in' because your webserver has checked that the visitor has valid credentials for that username, and set the header accordingly.
If you trust your webserver (e.g. Apache) to set the REMOTE_USER (or other) header correctly, then it's not a security flaw.
You can see the documentation here. A user can't send a request with customer header for REMOTE_USER.
Warning
Be very careful if using a RemoteUserMiddleware subclass with a custom HTTP header. You must be sure that your front-end web server always sets or strips that header based on the appropriate authentication checks, never permitting an end-user to submit a fake (or “spoofed”) header value. Since the HTTP headers X-Auth-User and X-Auth_User (for example) both normalize to the HTTP_X_AUTH_USER key in request.META, you must also check that your web server doesn’t allow a spoofed header using underscores in place of dashes.
This warning doesn’t apply to RemoteUserMiddleware in its default configuration with header = 'REMOTE_USER', since a key that doesn’t start with HTTP_ in request.META can only be set by your WSGI server, not directly from an HTTP request header.

Subdomains and Logins

If you multiple subdomains e.g.:
sub1.domain_name.com
sub2.domain_name.com
Is there a way to have a user be able to log into both of these without issues and double login issue?
The platform is Python, Django.
Without information regarding what platform you are using, it is difficult to say. If you use cookies to store authentication information, and you are using subdomains as you describe, then you can force the cookie to be issued for the highest level domain, e.g. domain_name.com.
This will be accessable by both sub1 and sub2, and they could each use that for their authentication.
EDIT:
In the settings.py for each application running under the subdomains, you need to put
SESSION_COOKIE_DOMAIN = ".domain_name.com" as per the django docs
Yes. Just set the cookie on the domain ".domain_name.com" and the cookie will be available to sub1.domain_name.com, and sub2.domain_name.com.
As long as you maintain your session information on both domains, you should be fine.
This is a very common practice, and is why you can log into your Google Account at http://www.google.com/ and still be logged in at http://mail.google.com.

Categories