Skip to content

[L2] Cookie 安全属性完整解析

一句话结论

HttpOnly 防 XSS 窃取、Secure 防明文传输、SameSite 限跨站携带;Domain/Path 精确控制作用域以最小化攻击面。


体系讲解

1. 五大安全属性速览

属性防御目标缺失时的风险
HttpOnly阻止 JS 读取 Cookie(document.cookieXSS 攻击可直接窃取 Session Cookie
SecureCookie 仅通过 HTTPS 传输HTTP 明文传输时遭中间人嗅探
SameSite限制跨站请求携带 CookieCSRF 攻击可利用自动携带的 Cookie
Domain指定哪些域名可接收 Cookie设置过宽导致子域可读取父域 Cookie
Path限制 Cookie 发送的 URL 路径范围同域不同路径的页面可获取不该获取的 Cookie

2. HttpOnly——阻断 XSS 到 Session 的最后一跳

HttpOnly 标记后,浏览器拒绝 JS 通过 document.cookie 读取该 Cookie,XSS 脚本即使注入成功也无法提取 Session ID。

注意 HttpOnly 不能防止

  • CSRF(Cookie 在 HTTP 请求中仍自动携带)
  • 网络层嗅探(需配合 Secure

3. Secure——保护传输通道

Cookie 只在 https:// 连接中发送,防止明文 HTTP 下遭网络嗅探。

典型风险场景:同一站点同时提供 HTTP 和 HTTPS,若未设 Secure,用户访问 http:// 页面时浏览器会将 Cookie 随请求发出,攻击者在同一网络下即可捕获。

设置 SameSite=None 必须同时设置 Secure,否则 Chrome 80+ 会拒绝该 Cookie。

4. SameSite——跨站 Cookie 携带控制

跨站 POST跨站顶层 GET 导航跨站 AJAX / iframe适用场景
Strict高安全性,但跳转回本站时 Cookie 不携带,影响体验
Lax(浏览器默认)平衡安全与体验,防大多数 CSRF
None第三方嵌入(OAuth 回调、跨域支付)场景,必须同时设 Secure

SameSite 行为差异与 CSRF 防御详见《CSRF 攻防基础》,本题聚焦属性联合使用的安全矩阵。

5. Domain 与 Path——最小作用域原则

Domain

  • 不设时,Cookie 仅发送给精确设置它的域(最安全)
  • 设置为 .example.com(含前导点)时,sub.example.comapi.example.com 等所有子域均可收到该 Cookie
  • 攻击面:若攻击者控制某个子域(如通过 DNS 劫持或子域接管),可利用宽 Domain 读取父域 Cookie

Path

  • 默认 /,所有路径均发送
  • 设置为 /api/ 时,Cookie 只在访问 /api/ 前缀路径时发送
  • 注意:Path 不能替代安全控制,同域下 JS 仍可通过 iframe 或 document.cookie 读取其他 Path 的 Cookie(除非设 HttpOnly)

6. 联合防御矩阵

Session Cookie 推荐配置:

Set-Cookie: session_id=xxx;
  HttpOnly;
  Secure;
  SameSite=Lax;
  Path=/;
  Domain=example.com
攻击类型主要防御属性
XSS 窃取 SessionHttpOnly
网络嗅探Secure
CSRFSameSite
子域 Cookie 污染精确 Domain + __Host- 前缀

7. Cookie 前缀强化(__Host- / __Secure-

前缀浏览器强制要求效果
__Secure-必须有 Secure 属性防止 HTTP 页面覆盖 Cookie
__Host-必须有 Secure、无 DomainPath=/完全锁定到当前主机,防子域污染

考察意图

考察候选人是否理解各 Cookie 属性的防御层次(传输层、脚本层、跨站携带层、作用域层),以及能否在不同攻击场景下选择正确的属性组合,而非孤立记忆单个属性。


追问链

  1. HttpOnly Cookie 是否完全防止了 XSS 的危害?
    不能。XSS 代码虽无法读取 HttpOnly Cookie,但可以:直接以受害者身份发起请求(不需要 Cookie 值本身)、篡改页面内容(钓鱼/挂马)、读取非 HttpOnly 的其他 Cookie 或 localStorage。HttpOnly 只是将 XSS 的危害从"直接窃取 Session"升级为"需在线操作",不能替代 XSS 本身的修复。

  2. 为什么 SameSite=None 必须同时设置 Secure
    Chrome 80+ 将 SameSite=None; 无Secure 的 Cookie 视为无效并丢弃。原因是 None 允许第三方完整携带 Cookie,若通过 HTTP 明文传输,等同于完全暴露会话凭证;强制捆绑 Secure 是浏览器的最低安全底线。

  3. __Host- 前缀能防御什么额外的攻击面?
    浏览器强制:① 无 Domain 属性(Cookie 严格归属当前精确主机名);② Path=/(无法缩小 Path 欺骗);③ 必须 Secure。这组约束阻止了子域覆盖攻击——即攻击者控制 evil.example.com 后无法向 example.com 写入同名 Cookie 来覆盖合法 Cookie,因为带 __Host- 前缀的 Cookie 强制要求无 Domain。


易错点

  1. 认为 Path 是安全边界:同域的 JS 脚本可以通过创建 iframe(指向其他路径页面)或直接操作 document.cookie 绕过 Path 限制。Path 只控制 Cookie 随 HTTP 请求发送的范围,不能阻止 JS 读取。

  2. Domain 设置为带前导点的父域(.example.com:默认不设 Domain 时 Cookie 仅归属精确域名,手动设置成 .example.com 反而扩大了作用域,所有子域均可收到该 Cookie,引入不必要的攻击面。

  3. 认为 HttpOnly + Secure 就足够了,忽略 SameSite:缺少 SameSite 时,即使 Session Cookie 无法被 JS 读取,跨站表单提交仍会自动携带它,CSRF 攻击依然可行。


代码示例

php
<?php
// PHP 中通过 session_set_cookie_params() 统一配置 Session Cookie 安全属性
session_set_cookie_params([
    'lifetime' => 0,           // 浏览器关闭时过期(不持久化)
    'path'     => '/',
    'domain'   => 'example.com',  // 精确域名,不加前导点
    'secure'   => true,        // 仅 HTTPS
    'httponly' => true,        // 禁止 JS 读取
    'samesite' => 'Lax',       // 防 CSRF,兼顾体验
]);
session_start();

// 手动写入业务 Cookie 时同样需要设置安全属性
setcookie('pref', 'dark', [
    'expires'  => time() + 86400 * 30,
    'path'     => '/',
    'secure'   => true,
    'httponly' => false,   // 前端需要读取偏好设置,可不设 HttpOnly
    'samesite' => 'Lax',
]);

基于 Apache License 2.0 开源