Cookie 的SameSite 属性


Chrome 51 开始,浏览器的 Cookie 新增加了一个SameSite属性,用来防止 CSRF 攻击和用户追踪。

CRSF攻击 与 XSS攻击

CRSF攻击 - 跨站请求伪造攻击

  • Cross-site request forgery

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

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

XSS攻击 - 跨站脚本—代码注入

通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。

  • 使用HTTP only的Cookie来解决一部分XSS攻击。

SameSite 属性:

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

可以设置三个值。

1. Strict
2. Lax
3. None

1. Stirct

Strict 最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。

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

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

  1. Lax

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

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

导航到目标网址的 GET 请求,只包括三种情况:链接,预加载请求,GET 表单。详见下表。

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

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

从上面的表格可以看出,对大部分应用而言,post表单,iframe(iframe嵌入的web应用很多是跨站的,都会受到影响),ajax(可能会影响部分前端取值的行为和结果),image图片一般放CDN,大部分情况是不需要cookie;除了上面这些,还有jsonp请求,如果涉及到跨站也有可能会被影响。

  1. None

2020年2月份Chrome 发布的 80版本将 Lax 变为默认设置。这时,网站可以选择显式关闭 SameSite 属性,将其设为 None 。不过,前提是必须同时设置 Secure 属性(Cookie 只能通过 HTTPS 协议发送),否则无效。

  • 下面的设置无效。

      Set-Cookie: widget_session=abc123; SameSite=None
    
  • 下面的设置有效。

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

另外一点就是需要进行User-Agent检测,部分浏览器不能加SameSite=none

  • 在IOS12的Safari以及老版本的一些Chrome会把SameSite=none识别成SameSite=Strict,所以服务端必须在下发Set-Cookie响应头时jinxingUser-Agent检测,对这些浏览器不下发SameSite=none属性