PHP 会话安全性 - 金丝雀会话


PHP session security - canary session

我从2001年开始使用Classic ASP后学习PHP。

我已经到了如何保护我正在处理的网站的管理部分的地步,并且一直在阅读这里:

https://paragonie.com/blog/2015/04/fast-track-safe-and-secure-php-sessions

我已经看到将会话绑定到 IP 地址似乎是不好的做法 - 例如

检查$_SERVER['REMOTE_ADDR']是否匹配$_SESSION['ip']

取自上面的链接:

某些系统喜欢将会话绑定到特定的 IP 地址。通常不建议这样做;特别是 Tor 用户将难以保持身份验证。您也可以在此处强制实施此限制。

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();
}

我无法解决这个问题 - 博客文章是否说将会话绑定到 IP 地址是错误的,然后发布代码显示如何做到这一点?

或者他们使用的"金丝雀"会话代码实际上并没有将会话绑定到 IP 地址?

假设代码没有将会话绑定到 IP 地址,并且使用它是一个很好的做法,那么我对如何使用这个金丝雀会话有点困惑 - 一旦用户成功登录,我会把这个位放在我的登录页面上吗:

// 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;
}

然后将这些位放在任何受用户保护的页面的顶部:

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();
}

我还将为登录和管理页面使用 HTTPS。

PHP 处理会话的方式是为每个用户生成一个唯一的会话 ID,并将其存储在 cookie 中(默认名称 PHPSESSID)。这适用于 IP 更改,并在同一台计算机上的不同浏览器上提供不同的会话。

为了提供更高的安全性,您还可以在会话中保存用户 ip 和用户代理,并在每个请求上检查它们。我不确定 PHP 是否默认这样做,但实现起来相当简单。

您还可以在著名的框架(Laravel,Symfony等)上查找会话实现,以了解它们是如何做到的。我把它留给你进一步研究主题,因为它应该是一些谷歌搜索和阅读源代码。