Preventing Session Hijacking?

What’s the best practice to prevent session hijacking?

My application is a site where users can send messages to each over ect.

My session works like this…

  1. The user logs into there account with their username and password.
  2. If username and password exists in database then a session is created based on their profileID. e.g. -> session_register($profileID);
  3. The application then checks each page they view to make sure their session variable is set.
  4. If the user try’s to view a page when their session hasn’t been set it will redirect to a login/registration page.

The session variable doesn’t get shown in the url at all but it can be viewed by a user using javascript injection -> “javascript: alert(document.cookie);”

which will look something like “PHPSESSID=jh787y8urjdf877303HJKS”

Will this be enough to prevent against session hijacking if i make sure there was no xss holes for a user to inject a cookie grabber etc onto my site??

Here is what you need:
http://rooftopsolutions.nl/article/97

You can combine it with checking IP - it should be the same, and prevent users from posting scripts.

No. You should regenerate the session-id (Using session_regenerate_id), whenever the user’s privileges changes.
See: http://shiflett.org/articles/session-fixation

@kyberfabrikken

I know about this advice, but I understood it literally meant, "when your user is upgraded from say “editor” to “reviewer” ". ie when their privileges change.

This is pretty rare.

If privileges aren’t changing isn’t the only thing the OP can do to protect his users sessions to make sure all output is escaped so that the xss exploit cannot be used?

Thanks for any clarification you can provide on my misconception, if it is one.

It has bugged me for a while.

No, it means when the privileges associated with the session is upgraded. Eg. when you authenticate. It does not mean when the privileges of the user account changes.

Duh.

Right thanks for clarifying that. Lets see if I have got this.

So

if (session not started) {
start new session using session_regenerate_id();
}

correct?

Nope. The whole concept of session fixation is precisely that the session has already been started. Instead of stealing the victims session, the attacker creates a session (legitimately) and tricks the victim into using that. Thus, when the victim logs in, it will be on the session that the attacker has access to.

Another - and arguably better - way of preventing session hijacking, is by not using sessions for authentication. You can simply require login-credentials with each and every request. This has its own problems though; Such as the sending of user/pass in clear-text over the network. You can fix this by serving over a secure connection (ssl).

Forcing use of cookies would prevent session fixation.

Passing unique strings around in the query strings of URLs would prevent session hijacking.


/*
Session Security
Two popular forms of session attacks are session fixation and session hijacking.
Whereas most of the other attacks described in this chapter can be prevented by filtering input and escaping output, session attacks cannot. Instead, it is necessary to plan for them and identify potential problem areas of your application.
*/
/*
When a user first encounters a page in your application that calls session_start(), a session is created for the user. PHP generates a random session identifier to identify the user, and then it sends a Set-Cookie header to the client. By default, the name of this cookie is PHPSESSID, but it is possible to change the cookie name in php.ini or by using the session_name() function. On subsequent visits, the client identifies the user with the cookie, and this is how the application maintains state.  It is possible, however, to set the session identifier manually through the query string, forcing the use of a particular session. This simple attack is called session fixation because the attacker fixes the session. This is most commonly achieved by creating a link to your application and appending the session identifier that the attacker
wishes to give any user clicking the link.
*/
<a href="http://example.org/index.php?PHPSESSID=1234">Click here</a>
/*
While the user accesses your site through this session, they may provide sensitive information or even login credentials. If the user logs in while using the provided session identifier, the attacker may be able to “ride” on the same session and gain access to the user’s account. This is why session fixation is sometimes referred to as
“session riding.” Since the purpose of the attack is to gain a higher level of privilege, the points at which the attack should be blocked are clear: every time a user’s access level changes, it is necessary to regenerate the session identifier. PHP makes this a simple task with session_regenerate_id().
*/
session_start();
// If the user login is successful, regenerate the session ID
if (authenticate())
{
session_regenerate_id();
}
/*
While this will protect users from having their session fixed and offering easy access to any would-be attacker, itwon’t helpmuch against another common session attack known as session hijacking. This is a rather generic termused to describe any means by which an attacker gains a user’s valid session identifier (rather than providing one of his own).
For example, suppose that a user logs in. If the session identifier is regenerated, they have a new session ID. What if an attacker discovers this new ID and attempts to use it to gain access through that user’s session? It is then necessary to use other means to identify the user.
One way to identify the user in addition to the session identifier is to check various request headers sent by the client. One request header that is particularly helpful and does not change between requests is the User-Agent header. Since it is unlikely (at least in most legitimate cases) that a user will change from one browser to another while using the same session, this header can be used to determine a possible session hijacking attempt.
After a successful login attempt, store the User-Agent into the session:
*/
$_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
/*
Then, on subsequent page loads, check to ensure that the User-Agent has not changed. If it has changed, then that is cause for concern, and the user should log in again.
*/
if ($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT'])
{
// Force user to log in again
exit;
}

disable session.use_trans_sid
enable session.use_cookies session.use_only_cookies

Users can no longer use your site without cookies enabled, but this helps prevent session fixation.

You can also check referer headers as a very mild improvement.
If the referer header is not set, allow the session.
If the referer header is set, make sure the domain is yours.

php has a setting for this(session.referer_check) but it allows the substring to appear anywhere in the header. It’s better to be strict and force it to be the domain.

Be aware that it is up to the browser to send the referrer, therefore this can be easily spoofed.

It is known that many proxies actually set the referrer to that of the domain you are accessing.

I am not saying crmalibu is wrong for suggesting it; I’m only making you aware of this before you start relying on it more than other safe-guards.

On a side note,
I agree with both regenerating the session ID’s and turning off use_trans_id.
Why do you think cookies have to be enabled for most online banking sites? (I’ve checked a few, and all require this.)

I should have stated the purpose of checking the referer is to help against users who followed a malacious link or redirect from another website. It only helps under certain circumstances, and won’t always help, but theres little drawback to it.

Thanks for posting that ma201dq, and all the other comments.

I never liked sessions and generally steered away from using them.

I have always used a session-database-based login system, that encrypts the UA/IP combination for the Admin areas of my sites, and this has been rock solid.

But increasingly I am using sessions on the main site, for ease of use really, no personal data is involved, but I can feel myself relying on them more and more - but had really thought of them as just one better than cookies.

Still _ its good to have the options spelled out - no point in being lax, no JS no session.

Thanks all.

If you do check referrers, be aware that people who disable referrers in their browser will be vulnerable. In addition, some privacy software, instead of blanking the referrer field, send a dash (‘-’) or something else.

It’s doable without cookies, and it’s even more secure, but it’s very annoying on your part.

One small recommendation; something I always do. If you’re going to create a session id for a user, it’s a good idea to change it with every page request. That way the use will never have the same session id more than twice when going from page to page. Since it cycles, an attacker would have a harder time trying to hijack the session.

Not sure if this can even be applied to your situation, but meh. :slight_smile:

Is it worth regenerating the session ID for every request? I’m doing that on a site at the moment, so if a session id is hijacked, it becomes useless after the next page click

Heh, just noticed… the post above says the same thing

@stormrider

Well that’s two votes for the same thing.

So what is against doing it?

The fact that you break the browsers back-button and the ability to open multiple tabs to the same site.

surely, that only applies if the session ID is being propagated through the URL, rather than through a cookie?

Can you please tell me what book this is a part of? I’d like to check it out :slight_smile: