使用安全会话 cookie 在 HTTP 和 HTTPS 页面之间切换

Posted

技术标签:

【中文标题】使用安全会话 cookie 在 HTTP 和 HTTPS 页面之间切换【英文标题】:Switching between HTTP and HTTPS pages with secure session-cookie 【发布时间】:2011-08-16 03:27:43 【问题描述】:

更新:请注意,每个网站在不安全的 HTTP 和加密的 HTTPS 页面之间切换,都不可避免地容易出现SSL-strip。请考虑为整个站点使用 HTTPS,虽然这也不能阻止 SSL-strip,但至少这使用户可以安全地调用站点,如果他关心的话。对于需要切换的站点,这种方法可能仍然是最好的选择。

这是一个常见的场景,一个网站的页面包含敏感数据,只能使用 HTTPS 协议访问,而其他页面包含非关键数据。

我找到了一个解决方案,它允许在安全和非安全页面之间切换,同时保持会话,并且想向您询问有关概念中缺陷的任何提示。你可以在这里找到整篇文章: Secure session cookie with SSL (当然我也很高兴听到,它是安全的)。

问题

HTTPS 确保客户端和服务器之间的任何人都无法窃听我们的通信并防止中间人攻击。不幸的是,这不适用于 session-cookie,它也被发送到未加密的请求。

php 提供了带有 $secure 参数的函数 session_set_cookie_params(...)。这是我们需要的,但是当我们切换到不安全的页面时,我们会失去会话。

身份验证 cookie

身份验证cookie的想法是,当用户输入他的密码(增加他的访问权限)时,我们会在不安全的会话cookie之外创建第二个cookie,并确保只有加密的HTTPS页面才能访问它.

https://www.example.com/login.php

<?php
  session_start();
  // regenerate session id to make session fixation more difficult
  session_regenerate_id(true);

  // generate random code for the authentication cookie and store it in the session
  $authCode = md5(uniqid(mt_rand(), true));
  $_SESSION['authentication'] = $authCode;

  // create authentication cookie, and restrict it to HTTPS pages
  setcookie('authentication', $authCode, 0, '/', '', true, true);

  print('<h1>login</h1>');
  ...
?>

现在每个页面(HTTPS 和 HTTP)都可以读取不安全的会话 cookie,但包含敏感信息的页面可以检查安全身份验证 cookie。

https://www.example.com/secret.php

<?php
  session_start();

  // check that the authentication cookie exists, and that
  // it contains the same code which is stored in the session.
  $pageIsSecure = (!empty($_COOKIE['authentication']))
    && ($_COOKIE['authentication'] === $_SESSION['authentication']);

  if (!$pageIsSecure)
  
    // do not display the page, redirect to the login page
  

  ...
?>

攻击者可以操纵会话 cookie,但他永远无法访问身份验证 cookie。只有输入密码的人才能拥有身份验证 cookie,它始终通过加密的 HTTPS 连接发送。

非常感谢您的每一个回答!

【问题讨论】:

但是这样一个被窃听的会话 ID 仍然可以在非 HTTPS 页面上使用。 没错,但他只会看到不重要的数据。您可以使用 HTTPS 请求所有您认为有必要的页面。 让所有网站完全只使用 https 是我的建议。它不仅消除了此类问题,而且还改善了浏览您网站的每个人的一般隐私。如果您想在多个服务器和不同域之间保留登录数据,因为您想为位于不同位置的文件提供服务,那么更麻烦的问题来了...... 【参考方案1】:

一个更简单的替代方案:一直使用 TLS,而不是在安全和不安全连接之间来回切换,正在成为一种越来越被接受的替代方案。大部分额外的处理时间都花在设置安全隧道上,但这只完成一次并被缓存(通常)。后续流量的对称加密在现代处理器上非常非常快。认为这会导致服务器开销或可伸缩性问题的想法有些过时了。

在最近的一篇博客文章中,一位 Google 工程师报告说,当他们为 GMail 切换到仅使用 HTTPS 时,他们发现他们的服务器窃听率仅增加了 4%。 (找不到引文。)

【讨论】:

我也读过这篇文章,这似乎是一个真正的选择。我想到的一件事是,所有资源(如图片)也被加密,外部包含会导致部分加密的页面(在其他不安全的页面上)。你有关于 PHP 缓存的任何信息,它是否适用于 HTTPS? 谷歌文章在某处Adam Langley's blog。 是否有其他关于该主题的独立文章(基准)?每个人都参考这篇文章。 PHP 不受 HTTPS 影响。事实上,在 PHP 服务器前通过反向 SSL nginx 代理完成所有 HTTPS 工作非常流行,PHP 服务器完成所有处理并通过线路将未加密的数据发送到代理。喜欢so。

以上是关于使用安全会话 cookie 在 HTTP 和 HTTPS 页面之间切换的主要内容,如果未能解决你的问题,请参考以下文章

会话-cookie

没有 cookie 的安全会话管理

登录/会话 cookie、Ajax 和安全性

6 Cookies 和Session

在 PHP 中使用会话和 cookie 创建安全登录

使用HttpOnly提升Cookie安全性