Preventing session hijacking
Asked Answered
G

10

78

How do you prevent multiple clients from using the same session ID? I'm asking this because I want to add an extra layer of security to prevent session hijacking on my website. If a hacker somehow figures out another user's session ID and makes requests with that SID, how can I detect that there are different clients sharing a single SID on the server and then reject the hijack attempt?

EDIT

I have accepted Gumbo's answer after careful consideration because I've come to the realization that what I'm asking for is impossible due to the restrictions of a stateless HTTP protocol. I forgot about what is perhaps the most fundamental principle of HTTP, and now that I think about this question seems a bit trivial.

Let me elaborate what I mean:

After User A logs in on example.com, he is given some random session ID, for simplicity's sake, let it be 'abc123'. This session ID is stored as a cookie on the client side and is validated with a server-side session to ensure the user who logged in remains logged in as he moves from one webpage to another. This cookie of course would not need to exist if HTTP were not stateless. For that reason, if User B steals User A's SID, and creates a cookie on his computer with the value 'abc123', he would have successfully hijacked User A's session, but there is simply no way for the server to legitimately recognize that User B's request is any different from User A's requests, and therefore the server has no reason to reject any request. Even if we were to list the sessions that were already active on the server and try to see if someone is accessing a session that is already active, how can we determine that it is another user who is accessing the session illegitimately and not the same user who is already logged in with a session ID, but simply trying to make another request with it (ie navigate to a different webpage). We can't. Checking the user agent? Can be spoofed - but good as a Defense in Depth measure nevertheless. IP Address? Can change for legitimate reasons - but instead of not checking for the IP address at all, I suggest checking something like the first two octets of the IP, as even a user on a data plan network who constantly has a changing IP for perfectly legitimate reasons would only usually have the last two octets of their IP change.

In consclusion, it is the stateless HTTP that condemns us to never being able to fully protect our websites from session hijacking, but good practices (like the ones Gumbo has provided) will be good enough to prevent a good majority of session attacks. Trying to protect sessions from hijacking by denying multiple requests of the same SID is therefore simply ludicrous, and would defeat the whole purpose of sessions.

Grabble answered 2/9, 2012 at 4:28 Comment(3)
Well! checking first two octets of the IP is not effective as well. Different people using same internet service likely have same first two octets though they have different IP addresses as a whole.Demijohn
The first two octets may also legitimately change - for example in a large organisation where there are multiple internet gateways through different ISPs.Thera
The first two ip octets are almost guaranteed to change for a mobile phone switching from wifi to cellular data (someone leaving their home or office)Saucier
S
96

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:

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.

Simplicity answered 2/9, 2012 at 8:45 Comment(17)
+1 I agree. I would also mention that session id's must expire and that /dev/urandom should be used as the entropy_file. ( blog.ptsecurity.com/2012/08/not-so-random-numbers-take-two.html ). Also Session Riding, aka CSRF is a concern.Grow
I don't understand. If all session info is stored on the server, how could it not be possible to retrieve data that is stored on your own server? I've looked at PHP's session handler, but I don't think it accomplishes what I'm looking for, maybe I'm wrong?Grabble
@Grabble you are trying to prevent a session from being compromised, well this prevents common attacks used to compromise the session id.Grow
@Rook I'm aware of the points Gumbo has suggested. More than anything, I just want to learn whether PHP has a mechanism of retrieving all active sessions, and if not, why? It seems possible in theory because PHP sessions are server-side, so there must be a good reason to not have such a mechanism present because it would have huge benefits for the security of the website. Thanks.Grabble
@Grabble PHP does not have such a feature built-in; you would need to implement it yourself depending on the storage you chose. But how would that prevent session hijacking?Simplicity
@Simplicity Well, the idea is if I could get a list of the active sessions, then I can detect duplicate SIDs before logging the client in, and destroy the session effectively eliminating the threat of session hijacking.Grabble
@Grabble The session ID is to identify a session and thus it must be unique. If you know a session ID, you can use that session and have access its data. And that’s what happens during a session hijacking attack. The attacker simply sends the victim’s session ID to the server to use the same session as the victim.Simplicity
What if the attacker in the same LAN as of the user sniffs the users request and get the session ids?Counterbalance
@AnanduMDas HTTPS is a must, no matter in what network you are. Even an intranet should be considered as untrusted.Simplicity
@Simplicity I am not trying to say https is not a must, instead, even if u use https an attacker in the same LAN of yours can easily sniff your session cookie. So mere https implementation along with the methods you suggested won't work.Counterbalance
@AnanduMDas How would you eavesdrop a proper HTTPS connection?Simplicity
@Simplicity LAN Sniffing! It may be encrypted. But who cares?Counterbalance
@Simplicity You don't need to decrypt a cookie to use it. :)Counterbalance
@AnanduMDas But you need to decrypt the encrypted HTTP message to read the cookie.Simplicity
@Gumbo, I am following all the steps u suggested above, additionally I m trying to append loggedIn userId in SessionId(using form auth & InProc) but user was not authenticated at the time of SessionId generation and validation, Is it possible to append or I am doing something wrong.Starcrossed
would session.use_httponly = 1 conflict with having an SSL certificate and thus using only the https protocol?Tune
Ini directives session.entropy_file, session.entropy_length, session.hash_function are removed as of PHP 7.1.Ul
N
5

Can we do something like this.

Store session id in database. Also store the Ip address and the HTTP_USER_AGENT for that session id. Now when a request comes to the server containing that matching session id, Check from which agent and ip it is coming from in your script.

Can make this funda work by make common function or class for session so that every request is verified before it is processed. It would hardly take some micro seconds. But, If many users are visiting your site and you have huge database of sessions, then this might be little performance issue. But, It would surely be very secure compared o other methods like => Using regenerating sessions.

In regenerating session ids, there is again little chance of session hijacking.

suppose, user's session id is copied and that user is not working or active for sometime and no request is made to server with old session id asking to regenerate new one. Then In case session id is hijacked, hacker will use that session id and make request to server with that id, then server will respond back with regenerated session id and so that hacker can go on using the services. Actual user will no longer be able to operate because he is unknown of what the regenerated id is and what request session id is to be passed in request. Completely Gone.

Please correct me if i m wrong somewhere.

Nonfulfillment answered 17/6, 2014 at 14:13 Comment(1)
Trying to pin to IP address will potentially wreck anyone on a mobile network (at least in the U.S.), probably people with CGNAT, many corporate networks, and IPv6 privacy extensions. In these cases, especially when NAT is in play, IP addresses can change a lot.Saucier
C
4

There are lots of standard defenses against session hijacking. One of them is to match each session to a single IP address.

Other schemes may use an HMAC generated from:

  • the network address of the client's IP
  • the user-agent header sent by the client
  • the SID
  • a secret key stored on the server

The reason only the network address of the IP is used is in case the user is behind a public proxy, in which case their IP address can change with each request, but the network address remains the same.

Of course, to truly be secure, you really ought to force SSL for all requests so that the SID can't be intercepted by would-be attackers in the first place. But not all sites do this (::cough:: Stack Overflow ::cough::).

Characharabanc answered 2/9, 2012 at 7:42 Comment(12)
ip address is impractical, checking the user-agent is a joke espeically if its stored in a cookie value so the attacker knows what the UA is if he has the session token (but he should know that anyway if he knows the cookie value). You made no mention of cookie flags. Please read gumbo's answer. Also don't build your own session handler, PHP's session handler is better than this.Grow
@Rook: I don't see how the UA being stored in an encrypted cookie value is any worse than simply grabbing it from the header. The latter is the weakspot in this scheme, not the HMAC. Secondly, this type of scheme could be used on top of the PHP session handler. You don't have to build your own session handler. Lastly, as I said, the only true way to defend against hijacking is to use SSL. But short of that, these are measures you can take to attenuate the threat.Oiler
an hmac is not a method of encryption. Also, if the session id is stolen using XSS or by an OWASP A9 violation the attacker will also have the user-agent.Grow
@Rook: An HMAC is by definition encrypted (in the implementation I linked to, it's encrypted using SHA-1). If the attacker wanted to find out the UA string from the HMAC, they'd have to figure out what the secret key stored server-side is and then try to crack the HMAC. But, like I said, if they can get to the HMAC, then they can already see the unencrypted UA string, so why bother?Oiler
hmac means "hashed message authentication code", hashed != encrypted, authentication is different from secrecy and usually you need both. Also, I strongly dislike your session handler. Gumbo has the correct answer.Grow
@Rook: I strongly suspect you're trolling at this point, but how is using a cryptographic hash function to encrypt data not encryption? And what exactly is my session handler? As I already told you, everything I suggested in my answer is intended as a supplement to PHP's session handler. There's nothing here to suggest that you shouldn't use PHP's session handler or that contradicts Gumbo's answer.Oiler
Never confuse a hash function with an encryption function, this is probably the best way to spot a non-cryptographer. If you don't believe me try posting to crypto.stackexchange.com. Also you can't depend on an attacker controlled variable to enforce access control. Its like you are suggesting having a cookie variable that says is_hacker=false.Grow
@Rook: OK, for the proper crypto terminology, the correct adjective I should have used was "hashed", but it seemed redundant since we were already talking about an HMAC. That aside, it doesn't really change anything. It's incredibly difficult for an attacker to spoof the HMAC if they don't know the secret key that's stored server-side. It's not quite the same as having an is_hacker cookie that just has a "true"/"false" value.Oiler
spoof hmac? What on earth are you talking about? This is what i am talking about: addons.mozilla.org/en-US/firefox/addon/user-agent-switcher You are not proposing a security system because you are depending on an attacker controlled variable that will always be known to the attacker. If you have the session id you will ALWAYS have the incredibly predictable user-agent. So please delete this awful post and never recommend this system to anyone, EVER!Grow
@Rook: You need to get your own argument straight. You claimed that putting the UA in the HMAC cookie somehow lessens security. It took me this many posts just to explain to you how it doesn't. Did I not mention that the UA could be grabbed directly from the header in my VERY FIRST REPLY to you? The fact that the user can spoof their UA is why you don't use UA-matching only. But in the case where the attacker can see your HTTP traffic in plain-text (and send traffic on the same network address), then there is no defense, period. (This was acknowledged in my answer!)Oiler
@Rook: At the very least, this type of scheme allows you to detect some hijacking attempts where the attacker doesn't try to spoof their UA or are not on the same network or same IP (depending on how much you want to inconvenience your users). How is deflect some attacks worse than deflecting none? Or are you of the attitude that if you're not using SSL for all requests, that you just shouldn't try to prevent session hijacking at all?Oiler
SSL is required for for the life of the session(owasp a9). The only defense is preventing the id from being compromised in the first place.Grow
G
3

Session hijacking is a serious threat, it has to handle by using a secure socket layer for advanced application which involves transactions or by using simple techniques like using cookies, session timeouts and regenerates id etc as explained above.
When the internet was born, HTTP communications were designed to be stateless; that is, a connection between two entities exists only for the brief period of time required for a request to be sent to the server, and the resulting response passed back to the client. Here are a few methods which hackers follow to hijack the session

  • Network Eavesdropping
  • Unwitting Exposure
  • Forwarding, Proxies, and Phishing
  • Reverse Proxies

Always recommend SSL Secure Sockets Layer
Use cookies also to following ini_set() directives at the start of your scripts, in order to override any global settings in php.ini:

ini_set( 'session.use_only_cookies', TRUE );                
ini_set( 'session.use_trans_sid', FALSE );

Use Session Timeouts and Session Regenerate ID

<?php
// regenerate session on successful login
if ( !empty( $_POST['password'] ) && $_POST['password'] === $password )         
{       
 // if authenticated, generate a new random session ID
  session_regenerate_id();

 // set session to authenticated
  $_SESSION['auth'] = TRUE;

 // redirect to make the new session ID live

 header( 'Location: ' . $_SERVER['SCRIPT_NAME'] );
}                   
// take some action
?>
Goatish answered 17/4, 2019 at 21:53 Comment(1)
What's the point of $_SESSION['auth'] = TRUE; ? If the session is hijacked, all $_SESSION variables are inherited, including that one.Pistole
T
1

In my view you can store session id in database when users login and check everyone for the same before loggin in. delete the same session id which you have stored in database when users logout. You can easily findout session id of each and every user or else I can help you.

Tita answered 2/9, 2012 at 4:41 Comment(5)
storing the session id in the database weakens the session. An attacker can steal it with sql injection and login without having to break the password hash. use's php's session handler, don't roll your own.Grow
@Rook, I looked at PHP's session handler, but I'm not sure how I could use it as a solution to my problem. If you know how to implement PHP's session handler to reject multiple SIDs, kindly post it as an answer.Grabble
@Grabble Gumbo's answer is great. You use the protection systems that everyone else uses. Additionally, make sure your system is free from XSS flaws and owasp a9 violations, after all these are the most common two flaws that lead to a session compromise.Grow
@Rook, the PHP's session handler supports database storage.Cuttlebone
@Rook: If you've got an SQL injection vulnerability in your site, then you've already got serious problems. The solution isn't to move the SID out of the database (a perfectly reasonable place to put it), but to secure your SQL injection vulnerability--unless you're suggesting that a secure site shouldn't use an SQL database at all.Oiler
O
1

One of the easy implementations can be done by making a table in database , as logged users , then at login, update that table with user name and his SID , this will prevent other logins as same user , now at the time of log out , just run a simple query , which deletes the logged in data in database , this can also be used to trace logged in user on ur website at a time .

Ophthalmitis answered 2/9, 2012 at 4:45 Comment(1)
This is a solution to a different problem. This helps prevent a single user from logging in from multiple clients. The issue in question is how to prevent multiple individuals from pretending to be the same user and client.Bollen
N
1

Obviously when you'll set session cookie in the browser, that cookie is sent in the request. Now when request comes, Server will check the session id in database and grant access. To prevent that only its important to store agent and ip so that before checking server makes sure that sessions access is granted to the unique client and not the unique session id which can be hijacked.

Nonfulfillment answered 18/6, 2014 at 7:44 Comment(0)
C
0

I don't know about the coding part well. So I can tell u an algorithm to do this. Setting stuffs like SSL, or setting the session cookie to secure and httpOnly wont work if a user sniffs the session id from a LAN network(Provided user and attacker are in the same LAN).

So what you can do is, once the user successfully logs into the application, set unique token to each and every pages of the web application and keep a track of this at the server side. So that if the valid user sends the request to access a particular page, the token of that page will also be sent to the server side. Since the tokens are unique for a user for a particular session, even if the attacker can get the session id, he cannot hijack the users session as he cannot provide the valid token to the server.

Counterbalance answered 16/10, 2014 at 13:26 Comment(0)
R
0

@Anandu M Das:

I believe what you may be referring to is the use of session tokens with each session ID. This site can explain the use of tokens with sessions:

https://blog.whitehatsec.com/tag/session-token/

Although session tokens are easily compromised by an XSS attack, this doesn't mean that they should never be used. I mean let's face it, if something was compromisable by a security vulnerability on the server, its not the fault of the method, its the fault of the programmer who introduced that vulnerability (to highlight points made by Hesson and Rook).

If you follow proper security conventions and practicies and secure your site from SQL injection, XSS, and require all sessions be managed over HTTPS, then you can easily manage the potential attack from CSRF by use of server-side tokens, stored within the session, and updated everytime the user would cause a manipulation to their session (like a $_POST being submitted). Also, NEVER store sessions or their contents in a url, no matter how well you think they are encoded.

When the security of your users is paramount (which it should be), the use of session tokens will allow better or more advanced functionality to be provided without compromising their session security.

Religieux answered 26/9, 2015 at 22:42 Comment(0)
L
0

one way i have been using is to make $_SERVER['REMOTE_ADDR'] part of some session stored hash, which on validating from different IP would naturally fail, do it on start of every request...

ANNOYING IF USER CHANGES IP (mobile devices may connect/disconnect to Wifi etc, or router may disconnect and reconnnect with new IP to provider if longer time between requests...)

you can show them a NETWORK CHANGE DETECTED, PLEASE LOGIN AGAIN if want

  • not ideal, but strongly effective, forging fake proper remote addr is above the basic level knowlegde. But still not "unpenetrable" as is nothing else.. But nicely adds a new level of making it difficult.

U can choose to try combine as many other things as possible, as for example saving also user agent to match, and on every request saving a new cookie and invalidate old on server side...

Maybe for first step learn to save session id cookie with STRICT SameSite cfg

Linnlinnaeus answered 10/5, 2024 at 9:7 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.