Session Hijacking and PHP

PHP Session Hijacking

The term "session" is overloaded to mean different things on the server and in the browser. Browser sessions are at best tenuously connected to server sessions. "Session hijacking" refers to server sessions.

Server-side, a session has an ID (which is passed between the client and server), content (stored on the server) and potentially other properties, such as last access time. The session ID is usually passed as a cookie. In PHP the default name for the cookie is "PHPSESSID". If cookies aren't available, PHP will (optionally) use a query string parameter of the same name ("PHPSESSID"). This cookie (or query param) can easily be changed and therefore the session identifier can be changed too.

The contents of a session (i.e. containing the login state of a user) cannot be changed by the client, the data is stored on the server and can only be changed by a PHP script on that server. Note that in a shared-hosting environment (shared by other services or users), the sessions can be overwritten if using the default session storage directory (/tmp). To protect against that, either use a database through session_set_save_handler() or set a custom session directory using session.save_path with the proper directory permissions set (preferably 700 which means that only the owner (the PHP user) can read and write to it).

To protect against session hijacking, you must have other ways to identify the user against a session. This can be a user agent, IP address or another cookie. The previously mentioned methods are just workarounds, best way to protect against stealing of the session cookie is by using HTTPS if a session is involved. Do not forget to set the httponly flag to true using session_set_cookie_params()

Client-side, "session" is again overloaded and used in various contexts (e.g. session managers, which restore open pages when a browser is opened, session cookies and sessionStorage). We can try to combine these meanings (into what is by no means a standard one) by saying a browser session consists of a collection of views and their associated data. (By "view" I mean roughly tabs in tabbed browsers and windows in non-tabbed browsers; the DOM window object exposes a view to JS.) Each view has a history, a current page and page data. Page data for pages in the same domain is shared between views in a session; if two pages are in different domains or different sessions, they don't share data. Exiting the browser closes all open session(s), possibly saving part of the session(s) (e.g. histories, current pages, sessionStorage) so that a session manager can re-open them. Session cookies are cookies that are discarded when a session is closed; in other words, session cookies are non-persistant. Though a session cookie may hold a session ID, the two concepts are orthogonal (sense 4; session cookies can hold things other than session IDs, and session IDs can be stored in persistant cookies).

Whether two different views are in the same collection depends on the browser. For example, one browser may consider a session to consist of all tabs within a single window; separate windows are separate sessions. IE8 lets users create new sessions via the "New session" menu item. Otherwise, new windows and tabs are opened in the same session. Privacy modes also create new sessions.

In summary, browser sessions are indeed set by the browser, though it provides users various means of controlling browser sessions: creating new sessions, changing the history and current page in a view by browsing, saving and restoring sessions. A user could even change session data by editing sessions saved on disk, though this isn't a feature afforded by the browser. None of this has anything to do with session hijacking. Server sessions are created and managed by the server, but users can (attempt to) switch server sessions by changing the session ID their browser passes back to the server, which is the basis for session hijacking.

See also PHP Session Fixation / Hijacking.

Preventing session hijacking

Unfortunately, there is no effective way to unmistakably identify a request that originates from an attacker in opposite to a genuine request. Because most properties that counter measures check like the IP address or user agent characteristics are either not reliable (IP address might change among multiple requests) or can be forged easily (e. g. User-Agent request header) and thus can yield unwanted false positives (i. e. genuine user switched IP address) or false negatives (i. e. attacker was able to successfully forge request with same User-Agent).

That’s why the best method to prevent session hijacking is to make sure an attacker cannot find out another user’s session ID. This means you should design your application and its session management that (1) an attacker cannot guess a valid session ID by using enough entropy, and (2) that there is no other way for an attacker to obtain a valid session ID by known attacks/vulerabilities like sniffing the network communication, Cross-Site Scripting, leakage through Referer, etc.

That said, you should:

  • use enough random input for generating the session ID (see session.entropy_file, session.entropy_length, and session.hash_function)
  • use HTTPS to protect the session ID during transmission
  • store the session ID in a cookie and not in the URL to avoid leakage though Referer (see session.use_only_cookies)
  • set the cookie with the HttpOnly and Secure attributes to forbid access via JavaScript (in case of XSS vulnerabilities) and to forbid transmission via insecure channel (see session.cookie_httponly and session.cookie_secure)

Besides that, you should also regenerate the session ID while invalidating the old one (see session_regenerate_id function) after certain session state changes (e. g. confirmation of authenticity after login or change of authorization/privileges) and you can additionally do this periodically to reduce the time span for a successful session hijacking attack.

How exactly does session hijacking work in PHP?

Lots of good questions, and good on you for asking them.

First.. a session is just a cookie. A 'session' is not something that's part of the HTTP stack. PHP just happens to provide some conveniences that make it easy to work with cookies, thus introducing sessions. PHP chooses PHPSESSID as a default name for the cookie, but you can choose any you want.. even in PHP you can change the session_name.

Everything an attacker has to do is grab that session cookie you're looking at, and use it in its own browser. The attacker can do this with automated scripts or for instance using firebug, you can just change the current cookie values.

So yes, if I have your id.. I can steal your session if you didn't do anything to prevent it.

However.. the hardest part for an attacker is to obtain the cookie in the first place. The attacker can't really do this, unless:

  • They have access to your computer
  • They somehow are able to snoop in on your network traffic.

The first part is hard to solve.. there are some tricks you can do to identify the computer that started the session (check if the user agent changed, check if the ip address changed), but non are waterproof or not so great solutions.

You can fix the second by ensuring that all your traffic is encrypted using HTTPS. There are very little reasons to not use HTTPS. If you have a 'logged in' area on your site, do use SSL!!

I hope this kind of answers your question.. A few other pointers I thought of right now:

  • Whenever a user logs in, give them a new session id
  • Whenever a user logs out, also give them a new session id!
  • Make sure that under no circumstances the browser can determine the value of the session cookie. If you don't recognize the cookie, regenerate a new one!

Proper session hijacking prevention in PHP

Your configuration is awesome. You definitely read up on how to lock down php sessions. However this line of code negates a lot of the protection provided by your php configuration:
session_id(sha1(uniqid(microtime()));

This is a particularly awful method of generating a session id. Based on your configurations you are generating the session id from /dev/urandom which is a awesome entropy pool. This is going to be a lot more random than uniqid() which is already mostly a timestamp, adding another timestamp to this mix doesn't help at all. Remove this line of code, asap.

Checking the IP address is problematic, ip addresses change for legitimate reasons, such as if the user is behind a load balancer or TOR. The user agent check is pointless, it is like having a GET variable like ?is_hacker=False, if the attacker has the session id they probably have the user agent, and if they don't this value is really easy to brute force.

Prevent session hijacking, XSS and network eavesdropping in PHP?

Session hijacking - it is when somebody knows your session identification number, provides it to the severs and, for example, logins with your priveleges.

XSS - cross site scripting, it is connected with badly filtered forms, which allow bad guys to implement their javascript code and still, for example, you cookie files.
They are 2 different forms of attack.

About preventing session hijacking some tips:
1) Set php.ini directives:

session.use_only_cookies = 1 -> for using only cookie based session ids
session.use_trans_sid = 0 -> disable showing PHPSESSID in browser url

2) About sessions

session_start();// -> starts your session. 
//Your browser will accept http header with session id and store it.
//You will be identified by this session id, usually PHPSESSID

It is looking like that:

GET / HTTP/1.1
Host: example.org
User-Agent: Mozilla Compatible (MSIE)
Accept: text/xml, image/png, image/jpeg, image/gif, */*
Cookie: PHPSESSID=1234

When session started you can provide any data to php global array $_SESSION, like

$_SESSION['var'] = 'abc';

If someone knows your PHPSESSID, he can send the same http header to the server and start using it, like he is you.

So, the best way to avoid it:

a) use session_regenerate_id() everytime you provide any important data. It will delete old session number and generate a new one.

b) save in $_SESSION you fingers: ip adress and/or browser-agent. If they differs, than - it is not you. For example:

session_start();
if (isset($_SESSION['HTTP_USER_AGENT']))
{
if ($_SESSION['HTTP_USER_AGENT'] != md5($_SERVER['HTTP_USER_AGENT']))
{
//some code
}
}
else
{
$_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);
}

c) use SSL for providing sensitive data.

Hope, you'll find it usefull.

Effective way to protect session hijacking in php

"Change the PHPSESSID key altogether to something generic like id"

This is security through obfuscation and a weak on at that. The user only needs to view their cookies and put together which is being used for the session id to bypass this

"Generate token per page and put it on the page and then validate it as well as teh session."

this is an interesting idea. but what if the user has multiple pages open? can you support multiple tokens? when do the tokens expire?

"I would add a short session expiration."

Good idea but this might effect users who stay on a page for a long time and then hit refresh only to find that they are logged out too soon

"Add more variables to the session id and encrypt it, so it would be longer and harder to crack. Perhaps I would use RSA encryption."

why use RSA encryption? why not hash it with something one-way like SHA? don't forget to add salts or intialization vectors

"Put a logout button, so that the user will be able to terminate his session."

who ever hits the logout button? ;-)

"Use javascript to count the time, over 5 mins will alert the user to continue his session."

YES

"Save session in cookies only."

dont do this, save the data server side always. cookies can be manipulated as they are stored client side

as for your other comments: you can store your session variables in a database and this allows you to check for other things like ip address and the like (though you can check ip etc with custom session handling functions: http://php.net/manual/en/session.customhandler.php). However, if you use a database and you regenerate your session ID too frequently (e.g. with every page load) you'll find that if your user hits the refresh button rapidly the id will regenerate more quickly than your server can update it in the database and the session will be lost.

"How does session regeneration works, is the old session key destroyed automatically"

yes unless you write custom code then it depends on your custom code

I hope my answers were somewhat useful, but i recommend following the guidelines for OWASP for session management so that you follow best practices:
https://www.owasp.org/index.php/Session_Management_Cheat_Sheet

EDIT

im not sure what do you mean by token? do you mean token as in session id? What value would that provide?
Is your token a session variable? that doesn't make sense as it's value is stored server side the key to which is the phpsessid whose abuse you are trying to prevent.

Also- never count on a hacker's ability not to understand your logic. If they want to understand it they will.

lastly, why do you need so much security? there is such a thing as good-enough security (if you follow certain standards). you likely don't need to protect against foreign government hackers else you'd probably outsource this project. follow best practices outlined in easily googled tutorials or guidelines such as the OWASP one i provided above. It'll be sufficient :-)

edit
"Also, you say the optimal storage is database? what about the last method that I described against brute forcing"

database session storage isn't necessarily optimal. you use it when you need to such as when you load balance multiple web servers that need to share session data.

two ways to hinder brute force attacks are to 1) have a really long session id, and 2) regenerate it frequently

How to prevent session hijacking with php when all pages are loaded in index.php

I think you cannot prevent the other browser to stop generating the session file with the codes that you have written so far as because with every time you will reload the page a session file will be created on the existing session file like previously your session file was sess_98765eryu again when you will reload it will generate sess_324yiuyiui by replacing the first one. So now when you will open your link in different browser a new session file be generated but it will be blank if you will login with your credentials then the data will be filled into that new session file but again your session filename will be changed although the data in it will not change. I think this is a genuine process.

And to your session hijacking what codes you have implemented i think its true and also quite normal rather you can also study more about using Securing Session INI Settings along this you can also follow some good examples here how to prevent session hijacking with php. I hope this may help you. :)



Related Topics



Leave a reply



Submit