使用 PHP 维护负责任的会话安全有哪些准则?网络上到处都是信息,是时候将它们集中到一处了!

有帮助吗?

解决方案

为了确保会话安全,需要执行以下几项操作:

  1. 对用户进行身份验证或执行敏感操作时使用 SSL。
  2. 每当安全级别发生变化(例如登录)时,重新生成会话 ID。如果您愿意,您甚至可以在每个请求时重新生成会话 ID。
  3. 会话超时
  4. 不要使用寄存器全局变量
  5. 在服务器上存储身份验证详细信息。也就是说,不要在 cookie 中发送用户名等详细信息。
  6. 检查 $_SERVER['HTTP_USER_AGENT']. 。这为会话劫持增加了一个小障碍。您还可以检查 IP 地址。但这会给因多个互联网连接上的负载平衡等原因而更改 IP 地址的用户带来问题(我们的环境中就是这种情况)。
  7. 锁定对文件系统上的会话的访问或使用自定义会话处理
  8. 对于敏感操作,请考虑要求登录用户再次提供其身份验证详细信息

其他提示

一项指导方针是致电 会话重新生成id 每次会话的安全级别发生变化时。这有助于防止会话劫持。

我的两分(或更多)分:

  • 不相信任何人
  • 过滤输入,转义输出(cookie、会话数据也是您的输入)
  • 避免 XSS(保持 HTML 格式良好,请查看 PHPTAL 或者 HTML净化器)
  • 纵深防御
  • 不要暴露数据

关于这个主题有一本很小但很好的书: 基本 PHP 安全 作者:Chris Shiflett.

基本 PHP 安全 http://shiflett.org/images/essential-php-security-small.png

在本书的主页上,您会发现一些有趣的代码示例和示例章节。

您可以使用上述技术(IP 和 UserAgent),如下所述: 如何避免身份被盗

我认为主要问题之一(正在 PHP 6 中解决)是 register_globals。目前用于避免的标准方法之一 register_globals 是使用 $_REQUEST, $_GET 或者 $_POST 数组。

“正确”的方法(从 5.2 开始,虽然有一点 bug,但从 6 开始稳定,即将推出)是通过 过滤器.

所以而不是:

$username = $_POST["username"];

你会这样做:

$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);

甚至只是:

$username = filter_input(INPUT_POST, 'username');

本次会议固定文件 对攻击可能发生的地方有很好的指示。也可以看看 维基百科上的会话固定页面.

根据我的经验,使用 IP 地址并不是最好的主意。例如;我的办公室有两个 IP 地址,根据负载使用,我们经常遇到使用 IP 地址的问题。

相反,我选择将会话存储在服务器上域的单独数据库中。这样,文件系统上的任何人都无法访问该会话信息。这对于 3.0 之前的 phpBB 确实很有帮助(他们已经修复了这个问题),但我认为这仍然是一个好主意。

这是非常琐碎和明显的,但一定要 会话销毁 每次使用后。如果用户没有明确注销,这可能很难实现,因此可以设置一个计时器来执行此操作。

这里有一个好的 教程 关于 setTimer() 和clearTimer()。

PHP 会话和安全性(除了会话劫持之外)的主要问题与您所处的环境有关。默认情况下,PHP 将会话数据存储在操作系统临时目录中的文件中。无需任何特殊的想法或计划,这是一个世界可读的目录,因此您的所有会话信息对任何有权访问服务器的人都是公开的。

至于在多个服务器上维护会话。此时,最好将 PHP 切换到用户处理的会话,其中它调用您提供的函数来 CRUD(创建、读取、更新、删除)会话数据。此时,您可以将会话信息存储在数据库或类似内存缓存的解决方案中,以便所有应用程序服务器都可以访问数据。

如果您在共享服务器上,存储您自己的会话也可能是有利的,因为它可以让您将其存储在数据库中,您通常比文件系统拥有更多的控制权。

我像这样设置我的会话 -

在登录页面上:

$_SESSION['fingerprint'] = md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR']);

(配置页面上定义的短语)

然后在网站其余部分的标题上:

session_start();
if ($_SESSION['fingerprint'] != md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR'])) {       
    session_destroy();
    header('Location: http://website login page/');
    exit();     
}

php.ini

session.cookie_httponly = 1
change session name from default PHPSESSID

eq Apache 添加标头:

X-XSS-Protection    1

我会检查 IP 和用户代理以查看它们是否更改

if ($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']
    || $_SESSION['user_ip'] != $_SERVER['REMOTE_ADDR'])
{
    //Something fishy is going on here?
}

如果你使用 session_set_save_handler() 您可以设置自己的会话处理程序。例如,您可以将会话存储在数据库中。有关数据库会话处理程序的示例,请参阅 php.net 注释。

如果您有多个服务器,数据库会话也很好,否则如果您使用基于文件的会话,您需要确保每个网络服务器都可以访问相同的文件系统来读/写会话。

您需要确保会话数据是安全的。通过查看 php.ini 或使用 phpinfo(),您可以找到会话设置。_session.save_path_ 告诉您它们的保存位置。

检查文件夹及其父文件夹的权限。它不应是公开的 (/tmp) 或可由共享服务器上的其他网站访问。

假设您仍然想使用 php session,您可以通过更改 _session.save_path_ 设置 php 使用其他文件夹,或者通过更改 _session.save_handler_ 将数据保存在数据库中。

您可以在 php.ini 中设置 _session.save_path_ (某些提供商允许这样做),或者对于 apache + mod_php,在站点根文件夹中的 .htaccess 文件中设置:php_value session.save_path "/home/example.com/html/session". 。您还可以在运行时使用 _session_save_path()_ 设置它。

查看 克里斯·希弗利特的教程 或者 Zend_Session_SaveHandler_DbTable 设置和替代会话处理程序。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top