PHP Session cookie 随机不安全,无法替换安全 cookie,90% 的 Firefox 用户都受到影响

PHP Session cookie randomly being nonsecure, fails to replace secure cookie, 90% all Firefox users afflicted

催化剂:

Gecko Bug 1617361 是一个严重的 cookie-related 错误,Gecko 浏览器随机拒绝发送 HTTP Cookie header(要么极难重现,要么(对于外行)极难逃脱(只需清除 cookie))。后来发现 Gecko 不会报告非安全 cookie 无法覆盖安全 cookie 的错误。但是,在将 session cookie 名称从 session 更改为 session2 并将所有 security/domain 设置设置为 FALSE 之后,Gecko 仍然拒绝发送HTTP Cookie header。这个错误非常严重,它影响了 90% 的所有人的 Gecko 浏览器,有效地阻止了他们加载由我的平台提供支持的网站。作为从根本上反对垄断的人,我需要在各个方面解决这个问题。

哪些错误是哪些?

问题:

下面的 PHP 代码如何无法在任何请求上下文(在实时(或“生产”)服务器上)将 session cookie 设置为安全的,以及我将如何重写确保 session cookie 不仅在设置时安全的代码,而且在为后续页面请求重新初始化时始终 安全?

错误信息

下面是这个post的直接错误。此错误消息 仅在您在 Firefox 中转到 about:networking#logging 时生成,将 cookie:5 设置为“当前加载模块” (逗号分隔符)并在问题发生时记录下来,因此不仅是一个错误,而且是多个错误的困难和挫败感。这是它生成的错误消息:

W/cookie rejected because cookie can't save because older cookie is secure cookie but newer cookie is non-secure cookie

详情:

虽然有两个与此相关的错误 post 我试图解决的错误是当我的 PHP 代码恢复 session 但没有使 session cookie 安全。为了解决原始催化剂错误的问题,我的服务器现在使用 setcookie('session2',session_id(),time()+3600,'/',$_SERVER['HTTP_HOST'], FALSE, FALSE);,直到该错误和我自己的 PHP 代码都正常工作。

  • 我很乐意更新问题并提供任何其他相关代码。
  • 有问题的域链接在我的个人资料中,尽管正如我提到的,我现在已将 session cookie 设置为不安全。
  • 这个错误似乎在 local/WAMP 和 live/LAMP 环境中都会发生。

可接受答案的验证要求

  • 当 session cookie 拒绝以安全方式发送时,我需要能够重现它的出现(我的配置文件中的域是我平台 HTTP 行为的一个很好的例子)。
  • 我需要了解我的代码、环境 and/or PHP 本身导致此问题的任何错误。
  • 我需要能够可靠地知道 session 在所有情况下发送的 cookie 都是安全的,尤其是因为 Gecko 浏览器 不会在开发者控制台中告诉您错误(posted bug 1623284)。
  • 为我的任何client/server代码使用框架或库。

这是处理 session 的原始 PHP 代码:

<?php
if (substr($_SERVER['DOCUMENT_ROOT'],0,1) == '/' && isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on')
{
 ini_set('session.cookie_secure', 1);
 ini_set('session.gc_maxlifetime', 3600);
 session_set_cookie_params(3600);
}
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_samesite','Strict');
ini_set('session.use_only_cookies', 1);
session_name('session');
session_start();
?>

这有点棘手,但我希望我已经为您找到了解决方案。我假设 (1) 会解决您的问题。其他一切都是可选的,应该可以帮助您减少一些潜在的问题。

1.使用 samesite=Strict

时将您的域名添加到默认 cookie 参数

我能够使用您的代码片段重现您的问题。我的 Opera 浏览器没有显示 cookie,并且完全忽略了它们。

有趣的是,当在 CLI 上尝试 curl 请求时,set-cookie header 可用,这开始让我很困惑。

如果您启用 samesite=Strict,那么您必须在 session_set_cookie_params 内设置您的域,否则我的浏览器将忽略它。

session_set_cookie_params(3600, '/', 'cookie-test.local');

正在为我解决问题。

2。您的站点使用不同的设置发送了两次 "set-cookie" header

$ curl -I -X GET https://www.jabcreations.com/ | grep set-cookie
set-cookie: session2=e633d6fcb7fb426f86b065173bc6c8ab; expires=Wed, 18-Mar-2020 20:05:21 GMT; Max-Age=3600; path=/; secure; HttpOnly; SameSite=Strict
set-cookie: session2=e633d6fcb7fb426f86b065173bc6c8ab; expires=Wed, 18-Mar-2020 20:05:21 GMT; Max-Age=3600; path=/; domain=www.jabcreations.com

我能够使用以下代码重现这一点。我的 Opera-browser 也显示了特定请求 header-tab 中的错误。在 cookie 旁边,您会看到黄色的小 "hazard" 图标。在我的例子中,它显示我试图在 non-secure 连接上使用安全 cookie。

setcookie('session2', session_id(), time() + 3600, '/', "", false, false);
setcookie('session2', session_id(), time() + 3600, '/', "", true, true);

在这种情况下,我会尝试确定您的 session_ 函数用法和您的 setcookie() 用法。

因为你没有使用任何特定的框架,我会首先猜测自动加载器 and/or 一个 includerequire 语句,它在你的项目中使用了两次。

请告诉我您是如何在项目中加载文件的。

3。 (Offtopic) 您的站点正在为您的资产发送 cookie

我不确定您的资产是否真的需要这个,但我会避免为您的资产发送 cookie。我会说在大多数情况下,对您的资产进行 cookie 处理是无关紧要的。我会删除它们。这将减少浏览器中潜在的 cookie 冲突数量,并且 cookie 问题可以减少到相关请求。

4. (Offtopic) 对您的状况的微小改变

我不确定 HTTPS 是否始终为小写,但 php 的 $_SERVER documentation 指出:

Set to a non-empty value if the script was queried through the HTTPS protocol. Note: Note that when using ISAPI with IIS, the value will be off if the request was not made through the HTTPS protocol.

据此,我将条件更改为:

if (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') {
   // ssl mode..
}

这个问题和我以前遇到的很相似。 一个问题是 cookie 不会保存为安全的,并且当它们已经存在时安全无法在某些随机情况下重写。

我发现这是在我重定向用户之前发生的。 在进一步调查中向我表明,问题是较新的浏览器不允许没有 HTTPS 连接的安全 cookie,并且由于我在 URL 中重定向用户之前创建了 PHP 会话,所以问题发生了。

上面的理论你可以很容易地验证,如果你愿意,你也可以重现。 我希望至少可以帮助您排除。