Reputation: 425
So I've been reading into sessions and I have to say, I am confused. It seems that sessions are as 'broken' as could be security wise, why haven't they implemented more security checks in the sessions code itself...
Anyway, my question. I've found this website with a lot of session security checks: https://wblinks.com/notes/secure-session-management-tips/ reading through it most of them make sense to me. However, most confusing to me is WHEN too call these checks.
Do I call these checks on every page? On one hand it would make sense because someone could hijack, or other things, a session on every page right? On the other hand it would cost some extra time to complete these check on every page, overal maybe increasing load times?
At this moment I've got the following code.
<?php
if ($_SESSION['_USER_LOOSE_IP'] != long2ip(ip2long($_SERVER['REMOTE_ADDR']) & ip2long("255.255.0.0"))
|| $_SESSION['_USER_AGENT'] != $_SERVER['HTTP_USER_AGENT']
|| $_SESSION['_USER_ACCEPT'] != $_SERVER['HTTP_ACCEPT']
|| $_SESSION['_USER_ACCEPT_ENCODING'] != $_SERVER['HTTP_ACCEPT_ENCODING']
|| $_SESSION['_USER_ACCEPT_LANG'] != $_SERVER['HTTP_ACCEPT_LANGUAGE']
|| $_SESSION['_USER_ACCEPT_CHARSET'] != $_SERVER['HTTP_ACCEPT_CHARSET']
|| !isset($_SESSION['MY_SERVER_GENERATED_THIS_SESSION'])) {
// Destroy and start a new session
sec_session_destroy(); // Destroy session on disk
sec_session_start();
// Log for attention of admin and re-authenticate user...
}
if ($_SESSION['SESSION_START_TIME'] < (strtotime("-1 hour")) || $_SESSION['_USER_LAST_ACTIVITY'] < (strtotime("-20 mins"))) {
sec_session_destroy();
//Expire session and re-authenticate user...
}
function sec_session_start() {
setcookie("sid", // Name
session_id(), // Value
strtotime("+1 hour"), // Expiry
"/", // Path
".serellyn.net", // Domain
true, // HTTPS Only
true); // HTTP Only
// Store these values into the session so I can check on subsequent requests.
$_SESSION['_USER_AGENT'] = $_SERVER['HTTP_USER_AGENT'];
$_SESSION['_USER_ACCEPT'] = $_SERVER['HTTP_ACCEPT'];
$_SESSION['_USER_ACCEPT_ENCODING'] = $_SERVER['HTTP_ACCEPT_ENCODING'];
$_SESSION['_USER_ACCEPT_LANG'] = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
$_SESSION['_USER_ACCEPT_CHARSET'] = $_SERVER['HTTP_ACCEPT_CHARSET'];
$_SESSION['MY_SERVER_GENERATED_THIS_SESSION'] = true;
// Only use the first two blocks of the IP (loose IP check). Use a
// netmask of 255.255.0.0 to get the first two blocks only.
$_SESSION['_USER_LOOSE_IP'] = long2ip(ip2long($_SERVER['REMOTE_ADDR'])
& ip2long("255.255.0.0"));
$_SESSION['SESSION_START_TIME'] = time();
$_SESSION['_USER_LAST_ACTIVITY'] = time();
sec_session_start(); // Start the PHP session
}
function sec_session_destroy() {
session_unset();
session_destroy();
session_start();
session_regenerate_id(true);
}
My last question is, does the code above make sense or do you have any suggestions to make it better or less confusing. And should I include this on every page, or just a few pages?
Thanks in advance
Upvotes: 0
Views: 249
Reputation: 536339
Why haven't they implemented more security checks in the sessions code itself...
The usual ‘session’ model is that the session ID is a strong secret, and anything that leaks that ID is to be considered a vulnerability.
The other headers listed here are not secrets, and are likely to be falsifiable in many of the same scenarios that would cause the session ID to leak. So checking them is of less clear benefit; doing so is only a partial mitigation for session hijacking vulnerabilities. On the other side there are significant compatibility drawbacks:
$_SESSION['_USER_AGENT'] != $_SERVER['HTTP_USER_AGENT']
User agent can change if a browser upgrade happens inside a session, or in some cases without any restart where a user installs or upgrades a browser plugin/extension.
$_SESSION['_USER_ACCEPT'] != $_SERVER['HTTP_ACCEPT']
The accept header will change depending on what sort of resource it is expecting, so if you do something like serve an image from PHP this will break.
($_SESSION['_USER_LOOSE_IP'] != long2ip(ip2long($_SERVER['REMOTE_ADDR']) & ip2long("255.255.0.0"))
This is better than an exact IP match, but will still break for a mobile user switching from one telco or wifi network to another.
You can certainly use changes in these headers as a heuristic, for example to decide whether to require reauthentication on particular sensitive operations, or generally risk-rating transactions. But immediately breaking the session when any of them change will make the experience of using your site much worse for some users.
This is a trade-off, each application may want a different approach and may need to tie that into specific knowledge of the application's usage. Consequently most implementations of sessions dont' and can't really do this by default.
Upvotes: 1