Session fixation with session in cookies - security

There are a lot of questions and answers about session fixation on StackOverflow, however, I am still confused about one thing. People often suggest that storing session in cookies is not enough to overcome the session fixation issue and you should rotate the session id after login. I can imagine that if you only use the session id to identify a user, you may still be vulnerable to an attack. However, I would like to ask about one specific case.
Let's assume that you use a signed cookie to store the whole session. On login you put into the cookie an id identifying the user. After logout, you delete the id. You do not change the session id, but as you change the session itself and you sign it, I cannot see any attack scenario taking advantage of this design. Is session fixation still an issue and, hence, is session id rotation still necessary in this case? If yes, can you provide an attack that could be used? Thank you.

The basics of Session Fixation is that it’s possible for an attacker to make the victim use a session that the attacker has access to. This is generally done by inducing the victim to use a certain session ID that is known to the attacker and doesn’t change after authentication.
Now what you’ve described doesn’t sound like a session identifier but rather a simple client-side data storage of user authentication data.
But nonetheless, if you make the cookie data dependent on data that again depends on the authenticated user which additionally is signed by the server, it certainly will change after authentication and won’t be known to the attacker. Then the security of that scheme depends on its actual implementation.

Related

Session authentication with cookie: security issue

I have a simple "session authentication" mechanism:
each time a user logs in a session it's created on database server side, and it's session id is set encrypted as a "session cookie" to the client
on logout or browser instance closing, the session is either deleted or invalidated
I've read and understood that by stealing a cookie encrypting the session id within an active session one steals another identity, and for this reason permanent cookie should not be used.
Still, even if i used a cookie with an short expiration date the theft can still happen within it. Are there other steps to avoid this problem?
It's legit to just use a short expiration date (if so, what is a decent time frame?), or are there other complementary technique to work around this problem?
The best practice for session cookies is to not set an expiry time so that they are valid for the browser session. If you set an expiry time, the cookie becomes persistent, will be stored on disk on the client and so on - it increases the overall risk.
You are right that anybody that has the cookie can impersonate the user. To avoid that, you want to have the cookie set as httpOnly to avoid Javascript access (XSS) and secure so that it is only sent over https.
While there are depths to correct session management, it doesn't seem to make a lot of sense to encrypt the session id. What is the purpose of that encryption? The session id should just be a large random number (possibly encoded into a shorter string, but still), there should be no need to encrypt it.
The generic advice around session management is to not implement it yourself. There are too many pitfalls, and pretty much all frameworks (or languages) have a solid implementation that you can just use reasonably securely. Avoiding all the potential vulnerabilities is hard.

Session Replay vs Session Fixation vs Session Hijacking

Can anyone give a clear difference between session fixation, session replay and session hijacking attacks? I have read many articles, but the matter is still unclear between session hijacking and session replay attacks.
Both fixation and hijacking have ultimately the same goal - gaining access to a session. They only differ in how you achieve that.
Session hijacking is simply the act of stealing an existing, valid session cookie. Most commonly through sniffing network traffic (a MITM attack), but also through any other ways that a session ID may be leaked.
Session fixation is similar, but inverted - a pre-defined session cookie is planted into the victim's browser. So after the victim logs into a website, they will use the same session cookie that the attacker already knows, and thus the attacker-owned cookie is now authenticated and can be exploited.
Of course that requires an attacker to have temporary access to the victim's browser itself, but the principle is very simple - there's no need to steal the data if it is under your control in the first place.
Replay is a bit different and can mean two things ...
If the attacker already has access to a session cookie (via fixation or hijacking), then it's just the act of reusing the cookie for whatever they want.
Otherwise, it can refer to tricking the victim into re-submitting a previously valid request (with the same session cookie). For example, a user could be tricked into buying multiple quantities of a good that they only wanted a single unit of.
Note: I've used "session cookie" everywhere to simplify the explanations, but of course there are other means of transferring session IDs.
How to protect yourself against these attacks:
Use TLS (HTTPS) to prevent MITM attacks and thus the most common ways of hijacking. Also set the Secure flag on cookies, to prevent them being submitted over a plain-text connecition (i.e. browsers will only send when using the https:// scheme).
Set the HTTPOnly flag on cookies, so that e.g. JavaScript doesn't have access to the cookie. If JS can't access cookies, that also means it can't leak them (can't be hijacked), but there's lots of other ways to exploit client-side code.
Regenerate session IDs on every privilege-changing action a user performs (login, logout, login as admin - if there's an extra form for that), as well as on regular, short time intervals. This serves as a mitigation mechanism against all of the 3 attacks.
Have your application reject session cookies that don't match a server-side record, to prevent fixation.

If I don't send session ID by url do I need to cycle my session id on login

I've heard that my site can get attacked by hackers who:
Go to my site to start a session.
Somehow get a client to go to my site with the same session ID
The client logs in
When the attacker comes back to my site with the session id he has full access to that clients account.
I can see this being done if the session ID is passed by url and it makes sense to cycle it (session_regenerate_id) but is this needed if I just use session_start and I don't put the session id in url at any point in time?
There are session fixation attacks other than session-ID-in-URL. In particular, browser controls over cross-domain cookies are weak.
If an attacker has control over foo.example.com, for example by means of an XSS hole in an application running there, they can write a session ID cookie with parameter domain=example.com, which will then be passed to your application running at bar.example.com and hey presto session fixation.
As a developer you often don't have any control over what other vulnerable applications might be running in neighbour domains, so it is best to assume cookie injection can happen and recycle sessions on a princpal change.
Well, if the session ID is only transferd by a cookie (is not in the URL and you do not accept one in the URL) then it is not that important to protect against session fixation attacks by recycling the session ID.
However it is still good practice, as this could also help against a session cookie which was laying around longer time (and potentially be placed by a former user). So with most security practices it is the same here: just do it, even if you cant find a way it might get exploited.

Should session ID cookie be signed?

I was using the Node library https://github.com/expressjs/session and noticed that it requires a secret to be specified for signing the session ID cookie.
If just the session ID is being stored in the cookie, and not any data, what is the use in signing the cookie?
My reasoning is that if someone wanted to modify a session ID cookie, then that's fine if the session ID sufficiently long to prevent brute force attacks. Am I missing something?
I questioned this as well and the only answers I could think of were,
a) If someone (for no good reason?) changes the default session ID
generation to a non-cryptographically random session ID, signing it
helps prevent attackers generating valid session IDs.
b) Reduce round trips to the session store by validating the session
ID using the signature/HMAC. (I can only imagine this being a problem
for DoS attacks).
Both seem like valid reasons though using good session caching would negate the need for b) and assuming your library's users are daft enough to change the default session ID generation, it seems a bit much to safe-guard against their own stupidity when the majority of users would just use the default generation algorithm.
If you store just id of session there is not reason to encrypt it. You are right.
You need to encrypt if you store some session data inside cookie, not only id.
This will prevent users of changing session data.
A session_id cookie is anything (number or alphanumeric) which identifies a client to a server, which in turns stores (usually temporary) data on the server accessed through this session_id/key.
The point is, if the cookie is going to be passed forth and back over HTTP, it doesn't matter whether you have "signed" it or not. Any man-in-the-middle could get your "signed/encrypted session_id" and make further requests pretending be the proper user. And I mean, this attacker doesn't have to care which information is inside the encrypted data, he could pass the exactly same signed/encrypted data, and the server couldn't figure out if it comes really from the right user.
In cases like these, you have to figure out if the privacy is important, if so, don't think too much, you got have to use HTTPS. If you understand it is not so important, don't waste your "processing time" signing/encrypting and decrypting your session id.
This answer is valid only for signed session_id.
I believe the reason it is signed is so that it is not easily guessable. For instance if someone decided to use integers as session id's, you could easily impersonate another user's session by trying multiple numbers. I believe that the signing makes it so that changing your session id value client side will not be valid (that is it prevents tampering).

Tricky question for good understanding of CSRF

My friend and I have a pari for beer.
From wikipedia:
Requiring a secret, user-specific
token in all form submissions and
side-effect URLs prevents CSRF; the
attacker's site cannot put the right
token in its submissions
The atacker can use browser cookies indirectly, but he can't use them directly!
That's why he can't put the cookies into the link using document.write()
Let us look how the logout link is generated. Is it secure way? Can this GET request be faked?
function logout(){
echo '<a href="?action=logout&sid='.htmlspecialchars($_COOKIE['sid']).'>Logout</a>';
}
sid is a session ID, generated for every session
on the server side, the following checking is performed:
$_GET['sid']==$_COOKIE['sid']
Absolutely not! Never use session identifiers for CSRF protection.
As far as why? Well, the answer is simple. Doing so opens the door for session hijacking attacks. Imagine someone copies and pastes the link for some reason into an email or onto the web. Now, the person on the other end of the email has the session identifier of that session. Sure, if they click the link it won't activate the session, but someone who knows what they are doing will still be able to use it.
And don't use a secret cookie either. Cookies are transmitted on every request. So the mere existence of a cookie does not verify that the user intended to make the request.
How to do it instead? Follow the OWASP recommendations. Use a unique, random token that's issued on each request and is associated with the session. Then verify that the token is valid on submission and then invalidate the token! It should be a one-time-use token only. Have it submitted by the form, and not attached to a link directly...
This prosed security system is immune to CSRF. The reason why this works is because in a CSRF attack the browser keeps track of the cookie, so the attacker doesn't need to know the cookie value when he is building the request. If this proposed security system where vulnerable to CSRF an exploit like the following Proof of Concept would log out a browser:
<img src=http://victim_site/index.php?action=logout&sid= />
Clearly in this case sid needs a value, and an attacker cannot obtain this value without using XSS, which makes this a moot point. Using xss an attacker can read a CSRF token to forge requests. This was used in the MySpace worm Sammy.
The use of the cookie a valid, however weaker form of CSRF protection. One problem is that it totally undermines http_only cookies. Ideally a CSRF token and a session id should be a Cryptographic nonce. However, it is more secure to have them be separate values.
Edit: This answer is at least partially wrong. Using the session ID as a CSRF token could lead to session hijacking if, eg, links are copy+pasted around. See ircmaxell's answer and comments.
Yes, because the session ID is both random and associated with the user, it would be an acceptable form of CSRF protection.
That said, it would be even safer to use a different random number, on the off chance that malicious JavaScript is able to grab the session cookie (and session ID)… But if I had to choose between “no CSRF token” and “session ID as a CSRF token”, I'd always pick the session as a CSRF token.
The only potential problem with using session IDs as CSRF tokens is: if someone was able to steal a CSRF token, they would also be able to hijack the associated session… But I can't think of a sensible scenario where that would be an issue.
Now, from the discussion on Marc B's answer, below: using a nonce would provide other benefits (like preventing duplicate form submissions)… But it isn't any more secure against CSRF attacks than the session ID (with the one caveat I mention in the first second paragraph).
See also: CSRF Validation Token: session id safe?
And what's to stop someone from editing the HTML that you send them, as well as the cookie, which you've also send them? Both are are under the control of the user.
With firebug I can trivially change the contents of any page, as well as any cookie.
Now, if you'd modified your version so that the SERVER stores that ID, then it would be harder to hack...
$_SESSION['form_token'] = 's33krit valu3';
if ($_POST['form_token'] == $_SESSION['form_token']) {
... everything's ok ...
}
Since the session data is kept on the server, out of the attacker's hands, this is far more secure than trusting the attacker won't think to modify the cookie.
You owe your friend a beer.

Resources