使用安全会话 cookie 在 HTTP 和 HTTPS 页面之间切换
更新:请注意,每个网站在不安全的 HTTP 和加密的 HTTPS 页面之间切换,都不可避免地容易出现 SSL-strip 。请考虑对整个站点使用 HTTPS,尽管这都不能防止 SSL 剥离,但至少这使用户可以安全地调用该站点(如果他关心的话)。对于需要切换的网站,此方法可能仍然是最佳选择。
这是一种常见的情况,网站的页面包含敏感数据,只能使用 HTTPS 协议访问,而其他页面则包含非关键数据。
我找到了一个解决方案,允许在安全和非安全页面之间切换,同时保持会话,并且想询问您有关该概念中的缺陷的任何提示。您可以在这里找到整篇文章: 使用 SSL 的安全会话 cookie (当然我也很高兴听到它是安全的)。
问题
HTTPS 确保客户端和服务器之间的任何人都无法窃听我们的通信并防止中间人攻击。不幸的是,这不适用于会话 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 连接发送。
非常感谢您的每一个回答!
Update: Note that every website switching between unsecure HTTP and encrypted HTTPS pages, is inevitable prone to SSL-strip. Please think about using HTTPS for the whole site, although this neither can prevent SSL-strip, at least this gives the user the possibility to call the site safely, if he cares. For sites that need to switch, this method is probably still the best option.
It's a common scenario, that a website has pages with sensitive data, which should be accessed only with the HTTPS protocoll, and other ones with noncritical data.
I found a solution which allows switching between secure and non secure pages, while keeping the session and would like to ask you for any hints about flaws in the concept. The whole article you can find here:
Secure session cookie with SSL
(of course i'm also happy to hear, that it is safe).
The problem
HTTPS makes sure, that nobody between client and server can eavesdrop our communication and prevents a man-in-the-middle attack. Unfortunately this doesn't apply to the session-cookie, it is sent to unencrypted requests too.
PHP offers the function session_set_cookie_params(...) with the parameter $secure. This is what we need, but it leaves us to the problem that we loose our session, when we switch to an unsecure page.
The authentication cookie
The idea of the authentication cookie is, that when the user enters his password (increases his access privileges), we create a second cookie additionally to the unsecure session-cookie, and make sure that only encrypted HTTPS pages have access to it.
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>');
...
?>
Now every page (HTTPS and HTTP) can read the unsecure session-cookie, but pages with sensitive information can check for the secure authentication 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
}
...
?>
An attacker could manipulate the session cookie, but he never has access to the authentication cookie. Only the person who entered the password, can own the authentication cookie, it's always sent over encrypted HTTPS connections.
Thanks a lot for every answer!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
更简单的替代方案:始终使用 TLS 正在成为越来越被接受的替代方案,而不是在安全和不安全连接之间来回切换。大部分额外处理时间都花在设置安全隧道上,但这仅完成一次并被缓存(通常)。后续流量的对称加密在现代处理器上非常非常快。认为这会导致服务器开销或可扩展性问题的想法有点过时了。
在最近的一篇博客文章中,一位 Google 工程师报告说,当他们将 GMail 切换到仅 HTTPS 时,他们发现他们的服务器监听仅增加了 4%。 (找不到引用。)
A simpler alternative: It is becoming an increasingly accepted alternative to use TLS all the time, rather than switching back and forth between secure and unsecure connections. The bulk of additional processing time is spent setting up the secure tunnel, but this is only done once and cached (typically). The symmetric encryption of subsequent traffic is very, very fast on modern processors. It's somewhat out-of-date thinking to believe that this would cause a server overhead or scalability issue.
In a recent blog post, a Google engineer reported that when they switched to HTTPS-only for GMail, they found their server overheard increased by only 4%. (Can't find the citation.)