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.
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:
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.