Chrome 80+关于跨站访问Cookies的巨大变动,导致登录失败

前言

最近有部分开发者同事的 Chrome 被自动升级到 80+的版本,然后发现 网页登录后的请求没带上 cookies,导致用户验证失败。

主要发生在:前端页面 和 后台服务 不在一台服务器上,ip或者域名不同,即跨站请求时出现的。

这是因为谷歌从2月17日开始对 Chrome80+ 开启了 SameSite="Lax"(限制跨站访问 Cookie)。
在这里插入图片描述

根据在线流量监控器StatCounter的数据,Chrome是最受欢迎的网络浏览器,这一变化将在2020年影响全球64%的互联网用户。请继续阅读以了解如何避免这种变化影响用户!

在介绍 SameSite 之前,先认识下 跨站 cookies,以及利用跨站 cookies 实现的 CSRF跨站攻击 和 用户追踪。

CSRF 跨站攻击

用一个示例来介绍:

受害者 Bob 在银行有一笔存款,通过对银行的网站发送请求 http://bank.example/withdraw?account=bob&amount=1000000&for=bob2 可以使 Bob 把 1000000 的存款转到 bob2 的账号下。通常情况下,该请求发送到网站后,服务器会先验证该请求是否来自一个合法的 session,并且该 session 的用户 Bob 已经成功登陆。

Set-Cookie:id=a3fWa;

黑客 Mallory 自己在该银行也有账户,他知道上文中的 URL 可以把钱进行转帐操作。Mallory 可以自己发送一个请求给银行:http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory。但是这个请求来自 Mallory 而非 Bob,他未登录,不能通过安全认证,因此该请求不会起作用。

这时,Mallory 想到使用 CSRF 的攻击方式,他先自己做一个网站,在网站中放入如下代码: <form src="http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory">,并且通过广告等诱使 Bob 来访问他的网站。

当 Bob 访问该网站时,上述 url 就会从 Bob 的浏览器发向银行,而这个请求会附带 Bob 浏览器中的 cookie 一起发向银行服务器。这时,悲剧发生了,这个 url 请求就会得到响应,钱将从 Bob 的账号转移到 Mallory 的账号,而 Bob 当时毫不知情。等以后 Bob 发现账户钱少了,即使他去银行查询日志,他也只能发现确实有一个来自于他本人的合法请求转移了资金,没有任何被攻击的痕迹。而 Mallory 则可以拿到钱后逍遥法外。

用户追踪

比如天猫就是通过淘宝的 JSONP 接口来判断用户是否登录的

SameSite 属性

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

它可以设置三个值。

  • Strict
  • Lax
  • None

Strict

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

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

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

Lax

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

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

导航到目标网址的 GET 请求,只包括三种情况:链接,预加载请求,GET 表单。详见下表。
在这里插入图片描述
设置了 StrictLax 以后,基本就杜绝了 CSRF 攻击。当然,前提是用户浏览器支持 SameSite 属性。

None

Chrome 已从2月17日将部分人群的 Lax 变为默认设置(以前的默认值是 None)。

这时,网站可以选择显式关闭 SameSite 属性,即将其设为 None。不过,前提是必须同时设置 Secure 属性(即表示 Cookie 只能通过 HTTPS 协议发送),否则无效。

下面的设置无效

Set-Cookie: widget_session=abc123; SameSite=None

下面的设置有效

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

解决办法

开发环境

如果是开发者,使用的 localhost,可以浏览器进入 chrome://flags/#same-site-by-default-cookies ,将 SameSite by default cookies 设为 disabled
在这里插入图片描述

生产环境

如果是正式发布的站点,有2种方式:

1、建议网站升级到 https,然后 cookies 中增加 SameSite=None; Secure 2个标识

如果不是 http,而又只设置了 SameSite=None; 是无效的。None 必须和 Secure 一起使用。
其实谷歌在建议大家都升级到 https。

如下图,没有设置 Secure 的 cookies,即使加了 SameSite=None 也有警告
在这里插入图片描述
在这里插入图片描述

2、使用反向代理,将不同站点代理成同一域名。
不存在跨站,就没有这个问题了

ASP.NET+IIS 如何设置 SameSite

1、.NET 4.7.2 及以后的版本 为自定义 cookies 设置 SameSite

var c = new HttpCookie("test");
c.SameSite = SameSiteMode.None;
c.Secure = true;

2、Form验证

编辑 web.config

<system.web> 之间加入

<authentication mode="Forms">
    <forms ..... cookieSameSite="Lax" />
</authentication>

3、ASP.NET 会话 cookie

编辑 Global.asax

void Session_Start(Object sender, EventArgs e)
{
    Response.Cookies["ASP.NET_SessionId"].SameSite = SameSiteMode.Lax;
    //while we're at it lets also make it secure
    if (Request.IsSecureConnection)
        Response.Cookies["ASP.NET_SessionId"].Secure = true;
}

4、.NET 4.8 中 cookie 的 “SameSite” 默认值是 Lax

可以修改 web.config

<system.web> 之间加入

<sessionState cookieSameSite="None" />

综合一下,可以在 web.config 的 <system.web> 中加上

<httpCookies sameSite="None" requireSSL="true" />
<sessionState cookieSameSite="None" />
<authentication mode="Forms">
    <forms cookieSameSite="None" />
</authentication>

微软文档说 <httpCookies> 加上 requireSSL="true" 就能在 cookies 中带上 Secure 标识了,但是实际上没效果,不知道是不是 bug。
在这里插入图片描述

最终在 Stack Overflow 上找到一个方法

<system.webServer>
    ...
    <rewrite>
        <outboundRules>
 
            <!-- 增加 "SameSite=None" 到所有 cookies 中-->
            <rule name="Add SameSite" preCondition="No SameSite">
                <match serverVariable="RESPONSE_Set_Cookie" pattern=".*" negate="false" />
                <action type="Rewrite" value="{R:0}; SameSite=None" />
            </rule>
 
            <!-- 当 https 访问,增加 "Secure" 到所有 cookies 中 -->
            <rule name="Add Secure" preCondition="No Secure">
                <match serverVariable="RESPONSE_Set_Cookie" pattern=".*" negate="false" />
                <action type="Rewrite" value="{R:0}; Secure" />
            </rule>
 
            <preConditions>
                <preCondition name="No SameSite">
                    <add input="{RESPONSE_Set_Cookie}" pattern="." />
                    <add input="{RESPONSE_Set_Cookie}" pattern="; SameSite=" negate="true" />
                </preCondition>
                <preCondition name="No Secure">
                    <add input="{RESPONSE_Set_Cookie}" pattern="." />
                    <add input="{RESPONSE_Set_Cookie}" pattern="; Secure" negate="true" />
                    <add input="{HTTPS}" pattern="on" ignoreCase="true" />
                </preCondition>
            </preConditions>
 
        </outboundRules>
    </rewrite>
</system.webServer>

上面的 rewrite 需要 IIS 安装 URL Rewrite 模块
在这里插入图片描述

rewrite 之后,就有 Secure
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神秘_博士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值