I've been doing a lot of research regarding sesion hijacking and I'm concerned at the number of codebases which seem to have poor implementations of defence against this. I feel I have a good understanding now at how to prevent this, such as:
- Always use TLS
- Set cookies over TLS, HTTP only and SameSite=Strict
- Change the session name from the default (in my case I'm also going to dynamically rotar it every so often with salt)
- Regenerate the session ID when a user authenticates / escalates privilege level, logs out etc
- Use PHP's strict mode for sessions along with switching off session IDs in URLs, only allowing cookie sessions & increasing the length/bits of the session ID
- Validate the IP address of the session
- Check the client user agent / browser / device etc
- Check the session running time to ensure it hasn't expired (I'm using a custom session handler and storing via the database)
- Add a seperate cookie with some other kind of login key / session key / device key hash etc which is used in conjunction with the session ID to verify the session is legitimate
- Properly dispose of the old session on logout and when regenerating the session ID
My question here really comes with using the additional cookie to verify the session. When using PHP sessions these automatically close when you exit the browser, so if a user checks "remember me" then I'd need an additional cookie anyway to verify the remember me details. So in this case I'd have: (1) the php session cookie (with the ID), (2) the cookie login key consisting of the device key or IP or some other hash used to verify the session cookie ID within the DB, and (3) the cookie with the remember me hash that automatically instantiates the session when the user visits the site again after closing the browser.
My issue is that I don't like this idea of instantiating a session via a single cookie because it feels very vulnerable... which is exactly why I've gone to such lengths to avoid a single session cookie ID. But if an attacker managed to get the php session cookie, they'd also manage to get the other cookie I set as well, making it pretty pointless. So how exactly can I set this securely or do something so that an attacker could never get all parts to instantiate a valid session? Particularly while using remember me.
The second part of my question is in relation to LAN networks.... let's say that we're in an office building with shared offices, and the network there doesn't use an internal TLS certificate meaning anyone can hijack sessions internally within that network (i.e. Wireshark). This is based on a very real use case as my old work has exactly this setup still in place. In this scenario, how can I tell that the session has come from a different machine? This could be a Coffee shop, McDonalds or any other public wi-fi service too. The only way I can think of is to check with the user agent / device, but again if the hacker (albeit internal) had access to the session cookie, they'd also have access to spoof the user agent etc as well because they'd know what user agent the other user was using.