I am learning PHP after using Classic ASP since 2001.
I've come to the point of working out how to secure the admin section of a site I'm working on, and have been reading here:
https://paragonie.com/blog/2015/04/fast-track-safe-and-secure-php-sessions
I've seen that it appears to be bad practice to bind a session to an IP address - e.g.
Check if the
$_SERVER['REMOTE_ADDR']
matches$_SESSION['ip']
As taken from the link above:
Some systems like to bind a session to a particular IP address. This is not generally recommended; Tor users, in particular, will have difficulty staying authenticated. You can enforce this restriction here too.
session_start();
// Make sure we have a canary set
if (!isset($_SESSION['canary'])) {
session_regenerate_id(true);
$_SESSION['canary'] = [
'birth' => time(),
'IP' => $_SERVER['REMOTE_ADDR']
];
}
if ($_SESSION['canary']['IP'] !== $_SERVER['REMOTE_ADDR'])) {
session_regenerate_id(true);
// Delete everything:
foreach (array_keys($_SESSION) as $key) {
unset($_SESSION[$key]);
}
$_SESSION['canary'] = [
'birth' => time(),
'IP' => $_SERVER['REMOTE_ADDR']
];
}
// Regenerate session ID every five minutes:
if ($_SESSION['canary']['birth'] < time() - 300) {
session_regenerate_id(true);
$_SESSION['canary']['birth'] = time();
}
I can't work this one out - is the blog post saying that it is wrong to bind a session to an IP address, and then posting code showing how you can do that?
Or is the "canary" session code they use not actually binding a session to an IP address?
Assuming the code isn't binding a session to an IP address and that it would be good practice to use it, then I'm a bit confused about how I would use this canary session - would I put this bit on my login page, once a user has successfully logged in:
// Make sure we have a canary set
if (!isset($_SESSION['canary'])) {
session_regenerate_id(true);
$_SESSION['canary'] = [
'birth' => time(),
'IP' => $_SERVER['REMOTE_ADDR']
];
}
// set my own session variable as well
if (!isset($_SESSION['name'])) {
$_SESSION['name'] = $name; // $name = value from database
header('Location:admin-home.php');
exit;
}
And then put these bits at the top of any pages which are user protected:
session_start();
// ####################################################################################################
// Is User Logged In?
// ####################################################################################################
$name = $_SESSION['name'];
if (!isset($name)) {
header('Location:login.php');
exit;
}
// ####################################################################################################
// Canary Session?
// https://paragonie.com/blog/2015/04/fast-track-safe-and-secure-php-sessions
// ####################################################################################################
if ($_SESSION['canary']['IP'] !== $_SERVER['REMOTE_ADDR']) {
session_regenerate_id(true);
// Delete everything:
foreach (array_keys($_SESSION) as $key) {
unset($_SESSION[$key]);
}
$_SESSION['canary'] = [
'birth' => time(),
'IP' => $_SERVER['REMOTE_ADDR']
];
}
// Regenerate session ID every five minutes:
if ($_SESSION['canary']['birth'] < time() - 300) {
session_regenerate_id(true);
$_SESSION['canary']['birth'] = time();
}
I will also be using HTTPS for the login and admin pages.