浏览器在请求时如何知道将哪些 cookie 发送到服务器?

Posted

技术标签:

【中文标题】浏览器在请求时如何知道将哪些 cookie 发送到服务器?【英文标题】:How browsers know what cookies to send to server when requesting? 【发布时间】:2012-02-07 00:33:14 【问题描述】:

我知道 cookie 是如何工作的,刚刚开始研究为什么 Codeigniter 不会将生成的 csrf 令牌存储在 SESSION 中,它只是存储在 cookie 中。考虑到安全性,我开始考虑 php setcookie() 函数参数,例如路径和域。我问自己是否可以从另一个域,从一些“www.evilsite.com”设置“evil_cookie”,路径=“/”和域=“www.goodsite.com”?还有一个问题是,在对 'www.goodsite.com' 执行请求时,'evil_cookie' 会被发送到 'www.goodsite.com' 吗?

所以,我做了一个测试。我创建了“set_cookie.php”文件并将其上传到一些“www.evilsite.com”:

setcookie('evil_cookie', 'gotcha', time() + 60 * 30, '/', 'www.goodsite.com');

我使用 Firefox 和 Firebug + Cookie 插件来查看发送和接收的 cookie。所以,在对“www.evilsite.com/set_cookie.php”的请求之后,我确实收到了“evil_cookie”。但是,cookie 没有保存(至少在 firebug cookie 插件面板中查看时没有这样的 cookie)。再次请求“www.evilsite.com/set_cookie.php”时也没有发送。刚收到但没有保存。

从 Firefox 浏览器的角度来看,仅为当前域保存 cookie 是合乎逻辑且安全的。恕我直言,那些设置 cookie() 参数(例如路径和域)主要用于管理当前域及其子域的 cookie,但不适用于外部域。我有点不高兴我无法在php.net 上找到相关信息,所以我不确定它是与浏览器相关的行为,以及它如何处理“第三方 cookie”的具体方式,还是它更像是一个标准?所有浏览器的行为都相同吗?如果此类声明有任何可靠可靠的来源,请分享。

这也与 cookie 的另一种用途有关——存储会话数据(不使用 PHP 本地会话,例如 Codeigniter 就这样做了)。因此,如果所有浏览器都不允许使用当前域以外的安全 cookie,那么没关系。但是,它不能防止 CSRF,因为“www.evilsite.com”可能包含恶意 javascript 代码,当用户执行并从“www.evilsite.com”获取请求时,这些代码将直接在客户端创建“evil_cookie”。

【问题讨论】:

$domain 在文档中的意思是像/forum/ 这样的相对路径,而不是整个网址。 我不同意。对于那些东西是'路径'参数。域是一个完整的域或子域。查看 php.net 【参考方案1】:

Cookie 受same origin policy 的约束:站点只能为自己的域写入和读取 cookie。

【讨论】:

那么,setcookie() 中的 domain 参数仅用于管理当前域及其子域的 cookie 可用性? -1 你错了。您可以在example.com 中设置一个cookie,该cookie 在www.example.com 中可用。【参考方案2】:

Cookie 只能为当前域或其子域设置,正如您已经发现的那样(否则,任何人都可以替换其他任何人的 cookie;随后会出现混乱)。这是由浏览器强制执行的:如果您尝试从服务器端(使用 HTTP 标头)为另一个域设置 cookie,浏览器将忽略 cookie。如果您尝试从客户端执行相同操作(使用 Javascript),same origin policy 将阻止您这样做。

因此,www.evilsite.com 可以使用 Javascript 为其自己的域设置 cookie,但这不是问题:它已经可以使用 HTTP 标头来执行此操作。这里没有新的攻击媒介。

【讨论】:

我在 accounts.google.com/signin 上。在 Chrome 开发工具/应用程序的 cookie 下,列出了两个域:accounts.google.com 和 accounts.youtube.com。两个完全不同的领域。在每个域下,所有 cookie 都遵循相同的来源策略。但是 APISID、SAPISIX 和 SID cookie 都存在于两者之下,具有相同的值。这些 cookie 是否在域之间共享?为什么 Goolgle.com 会在 chrome 开发工具中列出 YouTube 的 cookie?【参考方案3】:

[...] 是否可以从另一个域,从一些 'www.evilsite.com' 设置 'evil_cookie' 和 path='/' 和 domain = 'www.goodsite.com'?

不,用户代理应该忽略 Set-Cookie 指令,其 Domain 属性不domain-match 当前请求的域:

除非域属性,否则用户代理将拒绝 cookie 指定包含源的 cookie 的范围 服务器。例如,用户代理将接受一个带有 “example.com”或“foo.example.com”的域属性来自 foo.example.com,但用户代理不会接受带有 “bar.example.com”或“baz.foo.example.com”的域属性。

用户代理甚至不会接受此类 cookie。 PathSecure 属性也类似。

有关用户代理如何解释 Domain 属性值的示例,另请参阅 How do browser cookie domains work?

【讨论】:

以上是关于浏览器在请求时如何知道将哪些 cookie 发送到服务器?的主要内容,如果未能解决你的问题,请参考以下文章

如何检测服务器端是否禁用cookie

如何获取request请求携带的cookie

PHP Cookie

cookiesessionsessionStoragelocalStorage

Cookie不会在跨源请求中发送

如何从request中获取指定cookies