Cookie 的 SameSite 属性

一、CSRF 攻击是什么?

Cookie 往往用来存储用户的身份信息,恶意网站可以设法伪造带有正确 Cookie 的 HTTP 请求,这就是 CSRF 攻击。

举例来说,用户登陆了银行网站your-bank.com,银行服务器发来了一个 Cookie。

Set-Cookie:id=a3fWa;

用户接着又访问了恶意网站malicious.com,上面有一个表单。

<form action="your-bank.com/transfer" method="POST">
  ...
</form>

用户一旦被诱骗发送这个表单,银行网站就会收到带有正确 Cookie 的请求。如果没有预防措施,服务器分辨不出这是第三方网站发来的请求,会正常执行。

为了防止这种攻击,表单一般都带有一个随机 token,用来验证身份。

<form action="your-bank.com/transfer" method="POST">
  <input type="hidden" name="token" value="dad3weg34">
  ...
</form>

这种第三方网站引导发出的 Cookie,就称为第三方 Cookie。它除了用于 CSRF 攻击,还可以用于用户追踪。

比如,Facebook 在第三方网站插入一张看不见的图片。

<img src="facebook.com" style="visibility:hidden;">

浏览器加载上面代码时,就会向 Facebook 发出带有 Cookie 的请求,从而 Facebook 就会知道你是谁,访问了什么网站。

二、SameSite 属性

Cookie 的SameSite属性用来限制第三方 Cookie,从而减少安全风险。

它可以设置三个值。

  • Strict
  • Lax
  • None

2.1 Strict

Strict最为严格,完全禁止第三方 Cookie,任何情况都不会发送。换言之,HTTP 请求带有 Cookie,只有一种情况:当前 URL 与 HTTP 请求的目标一致。

Set-Cookie: CookieName=CookieValue; SameSite=Strict;

这个规则过于严格,可能会造成非常不好的用户体验。比如,当前网页有一个链接,用户点击跳转到 GitHub,这时不会带有 GitHub 的 Cookie,所以跳转过去总是未登陆状态。

2.2 Lax

Lax规则稍为放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。

Set-Cookie: CookieName=CookieValue; SameSite=Lax;

也就是说,如果当前请求可能导致恶意结果,就都不会带有 Cookie,比如<ifram><img><script>这一类的跨站点请求。除非这是会导致网页跳转的 GET 请求,详见下表。

请求类型 示例 正常情况 Lax
链接 <a href="..."></a> 发送 Cookie 发送 Cookie
预加载 <link rel="prerender" href="..."/> 发送 Cookie 发送 Cookie
GET 表单 <form method="GET" action="..."> 发送 Cookie 发送 Cookie
POST 表单 <form method="POST" action="..."> 发送 Cookie 不发送
iframe <iframe src="..."></iframe> 发送 Cookie 不发送
AJAX $.get("...") 发送 Cookie 不发送
Image <img src="..."> 发送 Cookie 不发送

设置了StrictLax以后,基本就杜绝了 CSRF 攻击。当然,前提是用户浏览器支持 SameSite 属性。

2.3 None

Chrome 计划将Lax变为默认设置。这样的话,自己就不用设置SameSite属性。

这时,网站可以选择显式关闭SameSite属性,将其设为None,使得浏览器发送第三方 Cookie。不过,前提是必须同时设置Secure属性(Cookie 只通过 HTTPS 协议发送),否则无效。

下面的设置无效。

Set-Cookie: widget_session=abc123; SameSite=None

下面的设置有效。

Set-Cookie: widget_session=abc123; SameSite=None; Secure
email

订阅匠人

youtubefacebookweibomeetup