As per the Django documentation, signed cookie session storage is vulnerable to a replay attack:
Note also that while the MAC can guarantee the authenticity of the
data (that it was generated by your site, and not someone else), and
the integrity of the data (that it is all there and correct), it
cannot guarantee freshness i.e. that you are being sent back the last
thing you sent to the client. This means that for some uses of session
data, the cookie backend might open you up to replay attacks. Unlike
other session backends which keep a server-side record of each session
and invalidate it when a user logs out, cookie-based sessions are not
invalidated when a user logs out. Thus if an attacker steals a user’s
cookie, they can use that cookie to login as that user even if the
user logs out. Cookies will only be detected as ‘stale’ if they are
older than your SESSION_COOKIE_AGE.
Does this mean that:
We are relying on the client-side expiration of cookies to ensure that the session data is destroyed (thus a replay attack is still possible if the cookie contents are captured before the cookie is removed by the browser), or
The server detects the staleness of the data (comparing with SESSION_COOKIE_AGE and explicitly rejects data it deems as stale.
It seems technically possible for Django to be able to determine how 'old' a session is without persisting this data server-side, but the docs don't seem clear about whether or not this is being done, or is Django relying on / trusting the user's browser to kill old cookies (and thus the session could still be replayed if the data was captured prior to its expiry).
Django, through SessionMiddleware, does set the HTTP cookie expiration to SESSION_COOKIE_AGE. This tells the browser when the cookie should be considered "too old" and expired. This is good housekeeping. Also, if the browser detects that a cookie should not be used anymore, it won't use it and this saves Django from spending time examining a cookie can't be used anyway.
However, Django does not rely on the browsers to ensure that expired cookies cannot ever be used again. A rogue agent could get a copy of the cookie and then reuse it past its expiration date. Django prevents this by sending the cookie to the browser formatted like this:
<payload>:<creation stamp>:<signature>
The colons are separators appearing literally in the data. <payload> is the actual session data. <creation stamp> is a time stamp added when the cookie is created, and <signature> is the MAC signature that signs the payload and the creation stamp.
You can see the relevant code in django.core.signing. The comments at the top of the file give you the basic signing scenarios using the Signer class. This class does not know about timestamps. However, when signing cookies, Django uses TimestampSigner, which does know about timestamps and produces the format I've shown above.
When TimestampSigner unsigns a cookie, it checks the timestamp and raises an exception if it is too old:
def unsign(self, value, max_age=None):
"""
Retrieve original value and check it wasn't signed more
than max_age seconds ago.
"""
result = super().unsign(value)
value, timestamp = result.rsplit(self.sep, 1)
timestamp = baseconv.base62.decode(timestamp)
if max_age is not None:
if isinstance(max_age, datetime.timedelta):
max_age = max_age.total_seconds()
# Check timestamp is not older than max_age
age = time.time() - timestamp
if age > max_age:
raise SignatureExpired(
'Signature age %s > %s seconds' % (age, max_age))
return value
Related
Django: Cookie set to expire in 30 seconds is actually expiring in 30 minutes? does
hr = HttpResponse('ok')
hr.set_cookie('user_id', user_id, max_age=30)
while https://stackoverflow.com/a/25179642/433570 does
request.session[user_id] = True
And both says we are setting cookie.
What's the difference between the two?
Can I set the expiration with the request.session method?
In short, cookies are intended to be stored in client side while sessions are stored in server-side (unless you're using cookie based session).
Users can clear http cookies from their browsers but they can't do anything about the sessions on your server. Clearing sessions is up you and your settings. There are some django settings you can use to determine their age like SESSION_COOKIE_AGE. For http cookies it's possible to set attributes like max_age, expires.
Choosing which one to use depends on your requirements; are you going to store sensitive data, is permanence important etc.
References:
Django sessions
Django request-response methods including set_cookie
Wikipedia HTTP cookies
we have a web service for some numerical computing. It has a registered mode, in which a user has to register to have its results sent by mail.
We would like to keep track of how long the user stays logged. The login time is written in the database upon successful registration. Registration in not permanent, it's just for the purpose of single session and is used for acquiring the user email.
There are a few situations possible:
User logs out normally via the logout button.
Simplest solution. Write the time and logout in the database, and delete session.
User logs out by session expiry.
I'm planning on having a script which would check all the database entries which don't have a set logout time and if current time - login time > expiry time write logout time in a database as login time + expiry time.
User logs out by browser close.
The sessions have a get_expire_at_browser_close() set to True. But i don't know how can the server detect browser closure.
Ideas, critics, comments?
In django session middleware these lines control session expiration if we want that SESSION_EXPIRE_AT_BROWSER_CLOSE:
if settings.SESSION_EXPIRE_AT_BROWSER_CLOSE:
max_age = None
expires = None
Server doesn't have to do detect anything as cookie that has no max_age or expires set should be deleted on the client side, according to this page:
By setting either of these, the cookie will persist until its time runs out, otherwise—if you set neither—the cookie will last until you close your browser (a “session cookie”).
Edit:
One way of tracking how long user was online is by using javascript that will ping server every now and then. It will happen only as long as the user has page opened in browser and on every ping server should update last seen online value for the user.
When user closes browser session is over. Next time user logs in server can calculate duration of his last visit as last seen online - last login time.
Simpler solution without using any javascript: last seen online could be updated on every user request using simple custom middleware.
I have a website which contains several rule sets for different kind of users.
One of the rules (permission) depends on the session expiration.
For instance, an unauthenticated users' session must be flushed when browser is closed however, authenticated users' sessions should live for a constant time.
Furthermore, for authenticated users some keys in the session may be deleted when the browser is closed but other should be kept alive.
How can I achieve this key-based session expiration in Django ?
You can do this by using the set_expiry method on request.session. The method takes either an integer for number of seconds to expire the session, a datetime or timedelta for when the session should expire, the integer 0 to indicate the session should expire at browser close time or None to indicate that the session should fall-back to the default timeout policy.
You should be able to write a piece of middleware that evaluates the criteria you have for session expiration then call set_expiry on the session before processing the request.
I'm implementing a login system very similar to that of Stack Overflow in one of my websites.
When we login to Stack Overflow, it creates a cookie named usr with some value.
If I delete this cookie, I will be logged out...
So, all that I can think is that it uses something like sessions, but in the database, to record the user sessions.
Is this right? Is it secure?
It's much like any other properly built login/session system. When you log in, the SO system generates a pseudo-random string to identify you uniquely - the session ID, which gets sent out via a cookie. When you return, the cookie is sent back to SO.
SO then takes the value in the cookie, looks up in its session system (could be flat files, could be a database, you just can't tell), finds the session represented by that session ID, and loads it up to process the request.
Deleting the cookie severs the link between you and the site - on your next visit, the session cookie (which you deleted) isn't sent, so SO has no way of identifying you, so it assumes a brand new user, and doesn't show you any of the "logged in" portions of the site.
I want to understand the logic of authorization,cookies,users logins,sessions..Do you know any source that explain and teach me about it. If it could give any examples it would be great. I mostly use php,jsp but it would be no problem if you give answer related other languages.
The cookie is primarily used to maintain some state on the client side between the requests on a specific domain and/or path. The session is primarily used to maintain some state on the server side between the requests on a specific domain and/or path.
The session is usually backed by a cookie. In PHP it's the cookie with the name PHPSESSID and in JSP it's the cookie with the name JSESSIONID. Both contains a long, unique autogenrated value.
The server side has a mapping between the cookie value and all attached session objects in the memory. On every request, it checks the cookie value in the request header and reveals the attached session objects from the mapping using the cookie value as key. On every response it writes the cookie value to the response header. The client in turn returns it back in the header of the subsequent requests until the cookie is expired.
With regard to authorization/logins, you can put the logged-in User object in the server side session and check on every request if it is there and handle accordingly. On logout you just remove the User object from the session or invalidate the session. In PHP you can access the session by $_SESSION and in Java/JSP by HttpServletRequest#getSession().
The principle is the same in all other web programming languages.