PHP会话安全

用PHP维护责任会话安全的一些准则是什么? 有networking上的信息,这是关于时间都落在一个地方!

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

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

一个指导原则是每次会话的安全级别发生变化时调用session_regenerate_id 。 这有助于防止会话劫持。

我的两个(或更多)分:

  • 不要相信任何人
  • filterinput,转义输出(cookie,会话数据也是你的input)
  • 避免XSS(保持你的HTML格式正确,看看PHPTAL或HTMLPurifier )
  • 国防深入
  • 不要暴露数据

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

基本的PHP安全http://shiflett.orghttp://img.dovov.comessential-php-security-small.png

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

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

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

做到这一点的“正确”方式(从5.2开始,尽pipe它有一个小错误,但是即将到来的6稳定)是通过filter 。

所以,而不是:

 $username = $_POST["username"]; 

你会做:

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

甚至只是:

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

这个会议固定文件有非常好的指针,可能会发生攻击。 另请参阅维基百科的会话固定页面 。

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

相反,我select将会话存储在我的服务器上的域的单独数据库中。 这样,文件系统上没有人可以访问该会话信息。 这对于3.0以前的phpBB来说真的很有帮助(他们已经解决了这个问题),但是我认为这仍然是一个好主意。

这是相当微不足道的,但确保在每次使用后session_destroy 。 如果用户没有明确注销,这可能很难实现,所以可以设置一个定时器来做到这一点。

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

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

至于维护多个服务器上的会话。 在这一点上,将PHP转换为用户处理的会话会更好,因为它会将您提供的函数调用到CRUD(创build,读取,更新,删除)会话数据。 此时,您可以将会话信息存储在数据库或memcache之类的解决scheme中,以便所有应用程序服务器都可以访问数据。

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

我把这个会议设置成这样 –

在login页面:

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

(在configuration页面上定义的短语)

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

 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注释。

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

你需要确保会话数据是安全的。 通过查看你的php.ini或使用phpinfo()你可以find你的会话设置。 _session.save_path_告诉你他们在哪里被保存。

检查文件夹及其父母的许可。 它不应该是公共的(/ tmp),也可以被共享服务器上的其他网站访问。

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

您可以在您的php.ini(某些提供程序允许)或apache + mod_php中设置_session.save_path_,并将其放在站点根文件夹中的.htaccess文件中: php_value session.save_path "/home/example.com/html/session" 。 你也可以在运行时用_session_save_path()_设置它。

检查克里斯Shiflett的教程或Zend_Session_SaveHandler_DbTable设置和替代会话处理程序。