Proper session hijacking prevention in PHP
I know this topic has been discussed a lot, but I have a few specific questions still not answered. For example:
// **PREVENTING SESSION HIJACKING**
// Prevents javascript XSS attacks aimed to steal the session ID
ini_set('session.cookie_httponly', 1);
// Adds entropy into the randomization of the session ID, as PHP's random number
// generator has some known flaws
ini_set('session.entropy_file', '/dev/urandom');
// Uses a strong hash
ini_set('session.hash_function', 'whirlpool');
// **PREVENTING SESSION FIXATION**
// Session ID cannot be passed through URLs
ini_set('session.use_only_cookies', 1);
// Uses a secure connection (HTTPS) if possible
ini_set('session.cookie_secure', 1);
session_start();
// If the user is already logged
if (isset($_SESSION['uid'])) {
// If the IP or the navigator doesn't match with the one stored in the session
// there's probably a session hijacking going on
if ($_SESSION['ip'] !== getIp() || $_SESSION['user_agent_id'] !== getUserAgentId()) {
// Then it destroys the session
session_unset();
session_destroy();
// Creates a new one
session_regenerate_id(true); // Prevent's session fixation
session_id(sha1(uniqid(microtime())); // Sets a random ID for the session
}
} else {
session_regenerate_id(true); // Prevent's session fixation
session_id(sha1(uniqid(microtime())); // Sets a random ID for the session
// Set the default values for the session
setSessionDefaults();
$_SESSION['ip'] = getIp(); // Saves the user's IP
$_SESSION['user_agent_id'] = getUserAgentId(); // Saves the user's navigator
}
So, my questions are
- do the
ini_set
's provide enough security? - is it okay to save the user's IP and navigator and then check it every time the page is loaded to detect a session hijack? Could this be problematic in any way?
- is the use of
session_regenerate_id()
correct? - is the use of
session_id()
correct?
Solution 1:
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.