编程

Cookie 安全标志

745 2024-04-22 18:10:00

为什么需要保护 cookie?

Web 浏览器使用 HTTP cookie 的最常见方式之一是用于用户身份验证和会话持久性。攻击者可以通过执行以下任何操作以恶意方式使用 cookie:

  • 窃取包含会话 ID 或身份验证 cookie 等敏感信息的 cookie
  • 重复使用被盗的 cookie 以访问经过身份验证的区域和现有用户会话
  • 伪造 cookie 以访问经过身份验证的区域和现有会话

有三种常见的攻击涉及 cookie 和上述恶意操作:

  • 跨站脚本(XSS)攻击中间人攻击(MITM)通常用于 cookie 窃取
  • 跨站点请求伪造攻击(CSRF)滥用浏览器处理 cookie 的方式,代表经过身份验证的用户执行恶意操作

如何保护 cookie?

HTTP 协议规范包含多种机制,开发人员可以使用这些机制来降低攻击者访问、重用或伪造带有敏感数据的 cookie 内容的风险。为了使用这些保护,开发人员在使用 Set-Cookie HTTP 响应头创建新的 cookie 时,会配置特定的参数和 cookie 值。这些参数会影响浏览器使用 Cookie  HTTP 请求头将 Cooki e发送回服务器的时间。

以下是所有 Set-Cookie HTTP 标头属性,可用于提高 Cookie 安全性 。

Expire 及 Max-Age 属性

ExpireMax-Age cookie 属性都定义了 cookie 的有效期。Expire 属性设置到期的绝对日期/时间 (语法: weekday, DD-MM-YYYY hh:mm:ss GMT),而 Max-Age 属性从设置 cookie 开始的时间限制。

如果 ExpireMax-Age 属性未设置,浏览器把此 cookie 当作会话 cookie,在浏览器关闭时删除该 cookie。如果设置了,则把它当作持久化的 cookie,将其保存在客户端,并根据 Expire Max-age 的值删除(按两者中更早的时间来)。

Secure 属性

Secure 标志指定 cookie 只能使用 HTTPS 连接(SSL/TLS 加密)传输,并且从不以明文形式发送。如果 cookie 设置有 Secure  标志,并且浏览器使用 HTTP 协议发送后续请求,则网页将不会在其 HTTP 响应中将此 cookie 发送到 web 服务器。

Secure 属性旨在防止中间人(MITM)攻击。但是,它只保护 cookie 的机密性,而不保护其完整性。在 MITM 攻击中,位于浏览器和服务器之间的攻击者不会通过未加密的连接从服务器接收 cookie,但仍然可以以纯文本向服务器发送伪造的 cookie。

请注意,只有安全连接才能设置Secure 标志。

Domain 属性

Domain 属性声明 cookie 将发送到的域。请注意,如果设置了域,cookie 也将发送到其所有子域。这意味着,如果您将域设置为 example.com,cookie 也将发送到 www.example.com 和 test.example.com。

如果未设置 Domain 属性,则 cookie 将仅发送到原始主机(不包括子域),但 Microsoft Internet Explorer 除外,它总是将 cookie 发送到子域(即使未设置 Domain 属性)。因此,最安全的方法是除非必要,否则不设置 Domain 属性。

Path 属性

Path 属性声明 cookie 将发送到的 URL 路径。请注意,这包括声明路径的所有子路径。例如,如果将路径设置为 /login/,则 cookie 将发送到 example.com/login/ example.com/login/admin/,但不会发送到 example.com/

如果将 Path 属性设置为 /,cookie 将发送到服务器上的所有 URL 路径。如果未设置 Path 属性,则默认值为设置 cookie 的路径及其所有子路径。因此,最安全的方法是除非必要,否则不设置 Path 属性。

HttpOnly 属性

引入 HttpOnly 标志是为了减轻 XSS 攻击。如果没有此标志,则可以使用 JavaScript 客户端脚本(通过 document.cookie)设置和读取 cookie。这意味着,如果 web 应用存在 XSS 漏洞,攻击者可能会窃取敏感 cookie。无论何时指定 HttpOnly,浏览器都将仅在响应 HTTP 请求时发送带有此标志的 cookie。

虽然 HttpOnly 属性保护敏感 cookie 的机密性,但它不能保护它们不被覆盖。这是因为浏览器只能为一个域存储有限数量的 cookie。攻击者可以使用 cookie jar 溢出攻击为域设置大量 cookie,从浏览器内存中删除原始 HttpOnly cookie,并允许攻击者在没有标志的情况下设置相同的 cookie。

SameSite 属性

SameSite 标志指示网络浏览器根据访问者与设置 cookie 的网站的交互方式,以不同的方式发送 cookie。此标志用于帮助防止 CSRF 攻击。

SameSite cookie 属性可能具有以下值之一:

  • SameSite=Strict: 只有当你当前在设置 cookie 的网站上时,才会发送 cookie。如果你在其他网站上,并单击指向设置 cookie 的网站的链接,则 cookie 不会与第一个请求一起发送。
  • SameSite=Lax: 不会为嵌入内容发送 cookie,但如果你触发顶级导航,例如单击 cookie 设置的网站链接,则会发送 cookie。它只与不更改状态的安全请求类型(如 GET)一起发送。
  • SameSite=None: 即使对于嵌入的内容,也会发送cookie。

请注意,如果未设置 SameSite 属性,则可能会出现不同的浏览器行为。例如,2019 年,谷歌 Chrome 浏览器改变了对同一网站 cookie 的默认行为。由于这种情况可能会随着时间的推移再次发生变化,我们建议定期检查你的应用在新浏览器版本中的表现。

如何声明 secure cookies?

以下是一个使用如下准则的安全 cookie 集示例:

  • 不设置 ExpiresMax-Age (因此 web 浏览器将其视为会话 cookie)
  • 不设置 DomainPath (尽可能地限制范围)
  • HttpOnly、SecureSameSite 设置成 Strict

Set-Cookie 标头示例:

Set-Cookie: sessionid=QmFieWxvbiA1; HttpOnly; Secure; SameSite=Strict

在 PHP 中设置上述 cookie 服务器端的示例:

setcookie("sessionid", "QmFieWxvbiA1", ['httponly' => true, 'secure' => true, 'samesite'=>'Strict']);

cookie 安全的有效性

在使用 cookie 时,必须记住,IETF 最初的 cookie 规范可以追溯到 HTML 的早期,并且在设计时没有考虑到网络安全。虽然上述属性有助于解决一些常见问题,但它们并不能保证应用程序的完整安全性。它们大多保护 cookie 的机密性,但不能防止 cookie 被操纵。

此外,请注意,尽管 cookie 标志可以防止许多攻击,但它们不应被用作跨站点脚本的唯一补救措施。攻击者可能会找到规避任何限制的方法——例如,cookie 可能会因冗长的调试消息或 phpinfo() 的暴露而泄露。

保护 cookie 免受攻击和维护 web 应用安全的唯一有效方法是发现应用中的任何漏洞并从源头消除安全问题。发现此类漏洞的唯一有效方法是执行手动 cookie 渗透测试(OWASP也建议这样做)和/或使用 Invicti 等自动漏洞扫描仪,该扫描仪还可以检测可能导致 cookie 暴露的错误配置。