# Cookie安全

## Cookie属性

`Ultimate` cookie：

```http
Set-Cookie: __Host-SessionID=3h93...;Path=/;Secure;HttpOnly;SameSite=Strict
```

### Secure属性

`Secure` 属性指示cookie仅在请求使用 `https:` 方案时发送到服务器（localhost除外）。它只保护cookie对MitM攻击者的**机密性** - 没有完整性保护。因此，具有此属性的cookie仍然可以通过访问客户端的硬盘或从JavaScript修改。

不安全的站点 `http:` 不能设置具有 `Secure` 属性的cookie（自Chrome 52和Firefox 52起）。对于Firefox，当 `Secure` 属性由localhost设置时，`https:` 要求被忽略（自Firefox 75起）。

### HttpOnly属性

标有 `HttpOnly` 属性的cookie不能从JavaScript访问。`HttpOnly` 属性只保护cookie的**机密性**。`HttpOnly` cookie可以通过从JavaScript溢出cookie jar来替换。

### Path属性

`Path` 属性指示请求URL中必须存在的路径，以便浏览器发送Cookie头。它可用于防止来自同一主机上其他应用程序对cookie的未授权访问。

正斜杠 `/` 字符被解释为目录分隔符，子目录也被匹配。例如，对于 `Path=/docs`：

* 请求路径 `/docs`、`/docs/`、`/docs/Web/` 和 `/docs/Web/HTTP` 都将匹配。
* 请求路径 `/`、`/docsets`、`/fr/docs` 将不匹配。

#### Cookie范围与同源策略

![](/files/7iSabIp0KRcB9Luo9DZf)

#### 隔离共享主机上的两个不同应用程序

![](/files/oUUt6Z5A0g5nBl2vFoAL)

### Domain属性

`Domain` 属性定义将向其发送cookie的主机。

* 如果未指定 `Domain` 属性，则默认为当前文档位置的主机，不包括子域
  * IE将始终发送到子域，无论
* 如果指定了 `Domain` 属性，cookie将发送到该域及其**所有子域**

### Expires属性

`Expires` 属性指示cookie的最大生存时间作为HTTP日期时间戳。

* 如果未指定 `Expires` 属性，cookie生存时间等于会话生存时间
  * 由浏览器决定会话何时结束
* `Non-persistent` 会话cookie实际上可能被持久化以在浏览器重启后生存

![](/files/F3NnE9hW0H9EfjaZEpsR)

参考资料：

* [MDN Web Docs - Document.cookie](https://developer.mozilla.org/en-US/docs/Web/API/document/cookie)

### Max-Age属性

`Max-Age` 属性指示cookie过期前的秒数。如果同时设置了 `Expires` 和 `Max-Age`，则 `Max-Age` 优先。

### SameSite

`SameSite` 属性防止浏览器将cookie与跨站点请求一起发送。`SameSite` 属性可以具有以下两个值之一（不区分大小写）：

* `Strict`，表示浏览器仅为同站点请求发送cookie，即来自设置cookie的同一站点的请求。如果请求来自与当前URL不同的URL，则不会发送具有 `SameSite=Strict` 属性的cookie。
* `Lax`，表示cookie不会在跨站点请求上发送，例如加载图像或框架的请求，但在用户使用 `safe` HTTP方法从外部站点导航到源站点时发送（例如，当跟随链接时）。如果未指定SameSite属性，这是默认行为。`safe` 方法：`GET, HEAD, OPTIONS` 和 `TRACE`。
* `None`，表示浏览器将cookie与跨站点和同站点请求一起发送。设置此值时还必须设置 `Secure` 属性，如 `SameSite=None; Secure`。

{% hint style="info" %}
在Chrome中，没有 `SameSite` 的cookie在最初2分钟内仍被视为 `None`，然后被视为 `Lax`，请查看 [Bypass SameSite Cookies Default to Lax and get CSRF](https://medium.com/@renwa/bypass-samesite-cookies-default-to-lax-and-get-csrf-343ba09b9f2b)
{% endhint %}

{% hint style="info" %}
请记住，同站点和跨站点请求不是一回事。SameSite cookie属性只关心跨站点请求。它不影响指向同一站点的跨源请求，请查看 [The great SameSite confusion](https://jub0bs.com/posts/2021-01-29-great-samesite-confusion/)
{% endhint %}

参考资料：

* [MDN Web Docs - Set-cookie: Browser compatibility](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Browser_compatibility)

## Cookie前缀

Cookie前缀允许您传递有关cookie的元数据并通知客户端已设置某些属性。支持以下前缀：

* `__Secure-` 告诉浏览器需要 `Secure` 属性。
* `__Host-` 告诉浏览器需要 `Path=/` 和 `Secure` 属性，同时 `Domain` 属性不应存在（因此，不能发送到子域）。

参考资料：

* [MDN Web Docs - Set-cookie: Browser compatibility](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Browser_compatibility)

## Cookie列表排序

[RFC6265](https://tools.ietf.org/html/rfc6265#section-5.4) 标准定义了cookie的顺序：

```
2.  用户代理应按以下顺序对cookie列表进行排序：

    *   具有较长路径的cookie列在具有较短路径的cookie之前。

    *   在具有相等长度路径字段的cookie中，具有较早创建时间的cookie列在具有较晚创建时间的cookie之前。
```

因此，如果易受攻击的应用程序使用第一个cookie，您可以通过添加具有较长路径的 `Path` 属性来强制它使用您的cookie。

## 参考资料

* [MDN Web Docs - Set-cookie](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gitbook.cdxiaodong.life/web-ying-yong-an-quan/cookie-security.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
