PHP Session Security

What are some guidelines for maintaining responsible session security with PHP? There's information all over the web and it's about time it all landed in one place!

84978 次浏览

每次会话的安全级别发生变化时都要调用 Session _ generate _ id 会话 _ 再生 _ id,这有助于防止出现会话劫持。

我认为其中一个主要的问题(在 PHP6中已经解决了)是 register _ globals。目前,避免使用 register_globals的标准方法之一是使用 $_REQUEST$_GET$_POST阵列。

The "correct" way to do it (as of 5.2, although it's a little buggy there, but stable as of 6, which is coming soon) is through filters.

So instead of:

$username = $_POST["username"];

你会做:

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

甚至只是:

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

这是非常琐碎和显而易见的,但是请确保在每次使用之后使用 session_destroy。如果用户没有显式注销,这可能很难实现,因此可以设置计时器来实现这一点。

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

PHP 会话和安全性(除了会话劫持)的主要问题在于您所处的环境。默认情况下,PHP 将会话数据存储在 OS 的 temp 目录中的一个文件中。没有任何特别的想法或计划,这是一个世界可读的目录,所以您的所有会话信息是公开的任何人访问服务器。

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

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

我会检查两个 IP 和用户代理,看看他们是否改变

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

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

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

如果使用 Session _ set _ save _ handle (),则可以设置自己的会话处理程序。例如,可以将会话存储在数据库中。有关数据库会话处理程序的示例,请参考 php.net 注释。

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

为了保证会话的安全,有几件事情要做:

  1. Use SSL when authenticating users or performing sensitive operations.
  2. Regenerate the session id whenever the security level changes (such as logging in). You can even regenerate the session id every request if you wish.
  3. Have sessions time out
  4. 不要使用寄存器全局项
  5. Store authentication details on the server. That is, don't send details such as username in the cookie.
  6. 检查 $_SERVER['HTTP_USER_AGENT']。这给会话劫持增加了一个小障碍。你也可以检查 IP 地址。但是对于那些由于多个互联网连接上的负载平衡而改变了 IP 地址的用户来说,这会导致一些问题(在我们的环境中就是这种情况)。
  7. 锁定对文件系统上会话的访问或使用自定义会话处理
  8. 对于敏感操作,请考虑要求登录用户再次提供其身份验证详细信息

您需要确保会话数据是安全的。通过查看 php.ini 或使用 phpinfo ()可以找到会话设置。_ session. save _ path _ 告诉你它们被保存在哪里。

Check the permission of the folder and of its parents. It shouldn't be public (/tmp) or be accessible by other websites on your shared server.

Assuming you still want to use php session, You can set php to use an other folder by changing _session.save_path_ or save the data in the database by changing _session.save_handler_ .

您可以在 php.ini 中设置 _ session.save _ path _ (一些提供程序允许) ,或者在 apache + mod _ php 中设置。你网站根目录下的 htaccess 文件: 也可以在运行时使用 _ session _ save _ path () _ 设置它。

选中 Chris Shiflett 的教程Zend _ Session _ SaveHandler _ DbTable来设置和替代会话处理程序。

这个会话固定文件 有非常好的攻击可能来点。参见 session fixation page at Wikipedia

我的两点(或更多)建议:

  • 不要相信任何人
  • 过滤输入,转义输出(cookie,会话数据也是你的输入)
  • 避免使用 XSS (保持 HTML 格式良好,看看 PHPTALHTMLPurifier)
  • 深度防御
  • Do not expose data

There is a tiny but good book on this topic: 基本 PHP 安全作者: Chris Shiflett.

PHP 基本安全 http://shiflett.org/images/Essential-PHP-Security-small.png

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

You may use technique mentioned above (IP & UserAgent), described here: 如何避免身份被盗

我这样安排我的治疗

登入页面:

$_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 add header:

X-XSS-Protection    1