PHP 会话的安全性如何


How secure are PHP sessions?

我主要是一个C++程序员,但我正在尝试学习一些PHP。

显然,实现 Web 用户会话的方法是使用 $_SESSION 变量将用户的登录 ID 存储在 cookie 中。

某人不可能只是修改他们的cookie,给他们不同的权限或以不同的用户身份登录吗?

似乎这种身份验证机制只是让用户将其ID存储在文件中 - 然后只是信任他们不会更改它。

有什么东西可以阻止这种情况吗?

谢谢!

PHP 会话只有在您的应用程序生成它们时才是安全的。PHP 会话将为用户提供一个伪随机字符串("会话 ID"),供他们标识自己,但如果该字符串被攻击者拦截,攻击者可以假装成该用户。

怎么办

此信息取自 PHP 手册中的"会话管理基础知识",但进行了一些简化。有些事情可能被遗漏了。请务必通读。

  1. 始终使用HTTPS

    • 防止攻击者读取会话 ID cookie
  2. 启用session.use_strict_mode

    • 拒绝未初始化的会话 ID
    • 确保创建的任何会话实际上都有效,因此您可以信任前缀(例如,如果前缀$userId-
  3. 启用session.use_only_cookies和禁用session.use_trans_sid

    • 通过共享包含会话 ID 的 URL 来避免用户意外共享会话 ID
    • 防止会话 ID 出现在Referer标头中
  4. 定期重新生成会话 ID,并在重新生成后不久使旧会话 ID 失效

    • 如果攻击者使用其他用户的会话 ID,则重新生成将使用户或攻击者的会话无效,具体取决于哪个发出重新生成 ID 的请求。然后,您可以跟踪某人何时尝试使用已重新生成的会话,并在此时使重新生成的会话失效。用户将能够登录,但攻击者(希望)将无法登录。
  5. (可选)跟踪与请求相关的$_SESSION中的其他信息(IP 地址、用户代理字符串等)

    • 如果攻击者以某种方式获得了对会话 ID 的访问权限,则可能会在攻击者访问任何数据之前检测到入侵。但是,请记住,这可能会恶化用户体验。例如,当用户从移动网络切换到 Wi-Fi 时,IP 地址可能会更改,而当用户的浏览器自动更新时,用户代理字符串可能会更改。根据您的网站愿意处理的权衡调整检查的数据。

否,会话存储在服务器上,用户无法访问。它用于存储整个站点的信息,例如登录会话。

下面是一个用法示例:

<?php
session_start();
if (password_verify($_POST['password'], $hash)) {
    $_SESSION['auth'] = true;
}
?>

然后,可以跨站点访问会话,以检查用户是否已通过身份验证。

<?php
session_start();
if ($_SESSION['auth']) {
    echo "You are logged in!";
}
?>

用户无法编辑这些值,但会话的 ID 通过 cookie 作为长随机字符串存储在计算机上。如果未经授权的用户获得了对这些字符串的访问权限,则他们有可能访问该站点。

如果这样做:

$_SESSION['user'] = $username;

然后$username不会直接存储在 cookie 中。相反,将生成一个唯一的会话 ID 并将其存储在 Cookie 中。

存储在$_SESSION中的信息仅存储在服务器端,永远不会发送到客户端。在客户端的后续请求下,服务器将在您执行session_start()时通过存储在cookie中的id加载会话数据。

它相对安全。唯一可能发生的情况是有人可以拦截会话 ID,从而窃取真实用户会话。HTTPS可以防止这种情况发生。

回答这个问题需要两种方法:

  1. 对于大多数用例,PHP 会话 ID 很难猜测。与其他广泛使用的系统相比,难度不大或低多少。

  2. 仅信任会话cookie
  3. (并且仅信任会话cookie的存在)对我来说似乎在安全性方面并没有走得太远,无论此会话cookie来自何处 - PHP还是其他地方。

所以,简而言之:PHP会话是安全的,就像你使用它们一样安全。对于我所知道的任何基于会话cookie的系统都是如此。

无论你在这个话题上得到什么答案,你很可能都不会满意,因为关于这个话题有很多不同的意见。甚至还有关于会话和PHP安全性的整本书。

您希望

在这里得到的最佳答案可能是"会话与您希望的那样安全"。更多的工作和更多的预防措施显然会使它们使用起来更安全,但实现本身会消耗更多的时间。与所有事情一样,您是衡量多少安全程度足以满足您的需求的人。

由于您是C++程序员,因此您只需要知道客户端可见的会话只是不同地址空间(服务器)上的指针,因此无法从客户端模式访问会话。