Cookie 的 SameSite、Secure、HttpOnly
Cookie 是会话的载体,也是攻击的焦点。三个安全属性各管一个方向,配置错误会留下真实的漏洞。
HttpOnly:防脚本读取
Set-Cookie: sid=abc; HttpOnly
JS 的 document.cookie 读不到带 HttpOnly 的 Cookie。它不能阻止 XSS 发生,但让 XSS 偷不走会话——攻击者从「接管账号」降级为「单页污染」。所有会话类 Cookie 都应加上,没有例外。
Secure:只走 HTTPS
带 Secure 的 Cookie 不会通过明文 HTTP 发送。如果站点 301 到 HTTPS,看似无影响,但中间人可以在首次 301 时窃取——所以 Secure 必须显式设置,不依赖重定向。
SameSite:控制跨站携带
| 值 | 跨站 GET 导航 | 跨站 POST/表单 | 第三方 iframe |
|---|---|---|---|
| Strict | 不带 | 不带 | 不带 |
| Lax(默认) | 带 | 不带 | 不带 |
| None | 带 | 带 | 带(须配 Secure) |
它主要防 CSRF(见专篇),也影响嵌入场景:第三方登录回调、iframe 内的会话、支付跳回。「从外链点进来显示未登录」多半是把 Strict 配成了全局,登录态 Cookie 用 Lax 更平衡。
Domain 与 Path
- 不设置 Domain:仅当前精确域名可见(host-only),这是更安全的默认;
Domain=example.com:所有子域共享——子域一旦被攻破(XSS 在某个测试子域),主域会话随之丢失;- Path 用处有限,别指望用 Path 隔离敏感 Cookie,JS 和同源请求仍然全量可见。
一个完整的会话 Cookie
setcookie('sid', $sid, [
'expires' => time() + 7200,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
常见症状对照
- 「登录后跳转回来就掉线」:检查 Domain 是否多域共用、SameSite=None 是否漏了 Secure;
- 「iframe 里一直未登录」:第三方 Cookie 被浏览器拦,需要 None + Secure,或改用 URL 传票据;
- 「XSS 演示能读到所有 Cookie」:会话 Cookie 漏了 HttpOnly。
给全站 Cookie 做一次属性审计(DevTools → Application → Cookies 逐列检查),半小时的工作量,收益贯穿整个安全基线。