通过 HTTP 提供的安全 cookie

Secure cookies available via HTTP

今天早些时候,我在检查我的一些子域上的 cookie 时注意到一些让我有点吃惊的事情。虽然我已将 PHP 设置为仅使用安全 cookie,但它们仍然可以使用 HTTP。

我的根域和我的大部分子域都是 HTTPS。事实上,它们本质上只是 HTTPS。我没有启用 HSTS,因为我有仅 HTTP 且不支持 HTTPS 的子域。 (基本上,我的域要么只有 HTTPS,要么只有 HTTP,而不是两者。)在导航到这些子域时,我注意到根域设置的 cookie 显示在浏览器开发人员工具中,并且似乎是根据请求发送到服务器的。

我宁愿不要发生这种情况,因为 a) 它不安全并且 b) 处理这些子域的服务器确实占用了这些 cookie,因此发送它们完全是一种不必要的风险可能会危及主要应用程序。

奇怪的是我的 cookie 已经安全了。所有的 cookies 都是这样设置的:

setCookie("my_cookie", $cookieValue, $expires, '/', $domain, true, true);

在我的会话管理器的顶部,我还有:

session_set_cookie_params(3600, '/', '.example.com', true, true);

最后 truesecurehttpOnly。有人会认为这使它们仅支持 HTTP:

HTTPS: Cookie with "Secure" will be returned only on HTTPS connections

To ensure that the session cookie is sent only on HTTPS connections, you can use the function session_set_cookie_params() before starting the session:

A cookie with the Secure attribute is sent to the server only with an encrypted request over the HTTPS protocol, never with unsecured HTTP, and therefore can't easily be accessed by a man-in-the-middle attacker. Insecure sites (with http: in the URL) can't set cookies with the Secure attribute. However, do not assume that Secure prevents all access to sensitive information in cookies; for example, it can be read by someone with access to the client's hard disk. https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies

但是你瞧,我在根域 continue 上设置的 all cookie 在我的纯 HTTP 子域上可用。使用开发人员工具,根域中 cookie 的任何更改都会继续反映在仅限 HTTP 的子域中!

我特意将 cookie 设置为 .domain 以使其在所有子域上可用,因为它们都共享会话信息并启用 SSO(即 HTTPS 域)。但是,我认为使用 secure 标志,这仍然会阻止 cookie 在仅限 HTTP 的子域上可用。这些参数中的一个是否优先于另一个? (我认为 secure 会)。

为什么这没有按预期工作?似乎因为 cookie 可用,即使我有 securehttpOnly,cookie 也可能从未加密的 HTTP 连接中被盗。是不是实际上没有发送 cookie,而是浏览器(错误地)将它们显示为存在,还是这里存在真正的安全风险?

浏览器开发人员工具似乎在显示域上可能可用的 cookie 和请求中实际发送的 cookie 之间进行了区分 - 也就是说,开发人员工具将显示子域的 cookie,即使它们永远不会根据请求发送到服务器。

以下是对根域的请求示例:

:authority: example.com
:method: GET
:path: /account
:scheme: https
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
cache-control: max-age=0
cookie: [cookies redacted]
dnt: 1
referer: [redacted]
upgrade-insecure-requests: 1
user-agent: [redacted]

以下是对 HTTP-only 子域的请求示例:

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
DNT: 1
Host: subdomain.example.com
If-Modified-Since: Wed, 27 May 2020 20:51:35 GMT
If-None-Match: "6c5-5a6a760afe782-gzip"
Upgrade-Insecure-Requests: 1
User-Agent: [redacted]

如您所见,cookie 没有随第二个请求一起发送。但是,如果您在浏览器中检查两个域上的 cookie,您会发现浏览器无论如何都会显示它们:

这可能会造成混淆,但检查请求 headers 表明浏览器确实会避免在不安全请求时发送安全 cookie。