导读
本文可以帮助你解决以下问题
- 想要了解一下SameSite属性(产生背景以及各个属性)
- 种跨域cookie有问题,猜测可能是SameSite引起的,需要解决
CSRF攻击
要了解SameSite产生的背景,我们先要了解一下CSRF攻击。如果你对此部分不敢兴趣,可以直接看SameSite部分。
什么是CSRF
CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。
一个典型的CSRF攻击有着如下的流程:
*受害者登录a.com,并保留了登录凭证(Cookie)。
*攻击者引诱受害者访问了b.com。
*b.com 向 a.com 发送了一个请求:a.com/act=xx。浏览器会默认携带a.com的Cookie。
*a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。
*a.com以受害者的名义执行了act=xx。
*攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。
我先举一个CSRF攻击的例子吧,如果你对CSRF攻击还不太了解的话,可以先参考前端安全系列(二):如何防止CSRF攻击?这篇文章,再来看这个案例,我们此次的案例是模拟百度地图的收藏操作。
我们搜索一家店铺,然后我们点击收藏操作,在chrome控制台分析一下发出的请求。
很明显,这是一个post请求,貌似是用cookie来验证登陆信息的,并且content-type为application/x-www-form-urlencoded。那么正好,我们可以新建一个网站,利用post表单来模拟一下此次CSRF攻击请求。假设场景是:我在用自己的账号登陆了百度地图,然后闲的没事儿,去某个小说网站看了会儿小说,然后一回来,突然发现自己关注了这一家串串店铺,我很疑惑,我并没有点击收藏,但是为什么收藏了这家店铺呢?
后来我查阅大量资料,最后得出结论,是这家小说网站存在问题,这家网站的html代码如下所示。
小说《斗破苍穹》此处省略几百万字
上面的html代码中,这个小说网站利用form表单的post请求发起了一个CSRF攻击,模拟了用户点击收藏的行为,并且骗过了服务端,成功收藏了这家店铺。
具体过程如下:当用户登陆了百度地图以后,百度地图域名下会种上用户登陆信息的cookie,每次对百度地图域名发起请求时,浏览器会默认带上这个cookie,服务端以cookie来校验请求发起人的身份。也就是说,小说网站对百度地图这个域名发起请求,也会带上用户登陆信息cookie,再加上post表单并没有跨域限制,所以最后成功模拟了用户的收藏操作。
这是不是很荒唐,如果你有兴趣去尝试一下的话,会发现很多网站其实也存在着这种安全问题,为了防止这种攻击行为,chrome很早就推出了cookie的SameSite属性来限制第三方cookie,但是大家伙都不理不睬。所以chrome干脆一不做二不休,在chrome80版本以后默认把cookie的SameSite属性设置为Lax,以此来对第三方cookie做一些限制,这样就能大大地降低被CSRF攻击的风险了。
但是chrome也很头疼,因为此次强制更新SameSite的默认策略,势必会给不少使用第三方cookie的系统造成大麻烦,所以chrome在年前就在控制台给出了黄色警告,此次chrome更新SameSite默认策略对于这些有使用第三方cookie场景的系统,往往会造成登陆异常,系统崩溃等大问题。
SameSite属性介绍
SameSite是cookie的一个属性,用来限制第三方Cookie。可以参考阮一峰老师的Cookie 的 SameSite 属性,或者直接看我画的下图。简单来说他有三个值:
Strict(禁止第三方 cookie)
Lax(稍微严格一点)
-
None (注意,cookie的SameSite设置为None以后,Secure需要同时设置为true,这意味着你的网站必须支持https)
Chrome80以后,cookie默认的SameSite策略是Lax。大家可以参考图一中的画出的SameSite为Lax时对第三方cookie的禁止情况,如果你有在POST表单,iframe,AJAX,Image这些场景中使用第三方cookie的情况,那么就需要注意了。
问题分析
包括登陆在内的很多信息都是存储在Cookie当中,但是浏览器的默认策略是允许第三方网站发起的请求中携带cookie,这样就会很容易遭到CSRF攻击。
Chrome浏览器从80版本开始更新默认的SameSite策略,新的策略为:在所有的 Cookie 中默认设置 SameSite=Lax 来屏蔽部分第三方 Cookie。
如果你正在使用Chrome浏览器,没有上线也没有更新,但是某天突然遇到第三方请求的cookie没有种上(比如登陆cookie没有种上,导致用户登陆不上)的情况,那你可能就需要考虑是不是Chrome80以后正在实行的新版SameSite策略造成的问题了。
案例
B站的html代码如下,iframe的src指向A站(SameSite.a.com)
比如A网站作为iframe嵌入在B网站中。某天我们突然发现在B网站中加载A网站的iframe时我们发起请求来setCookie,但是cookie并没有种上。
大致情况我们可以结合图二与图三来看,A站作为iframe嵌入在B站中,在B站中访问iframe(A站)时想要发起请求setCookie,但是失败。
以登陆信息(图中为loginToken)举例,大多数系统在用户访问时如果登陆信息校验失败,就会发起登陆请求,登陆请求setCookie的同时又会重定向到系统,所以页面可能就会反复跳转刷新,进入死循环。
如果出现第三方请求setCookie失效的情况,那么我们就可以使用以下操作来验证是否为SameSite的问题。
步骤如下:
Chrome浏览器地址栏输入 chrome: //flags/
找到:SameSite by default cookies、Cookies without SameSite must be secure
-
设置上面这两项设置成 Disable,重启浏览器
此时我们再次验证网页之前所存在的问题,如果问题解决了,说明你的浏览器确实存在SameSite策略的问题。
解决方法
如果你依然想采用http域名的话,可以使用方案一;如果方案一不可行的话,就升级到https。
方案一:统一主域名
将A网站与B网站的主域名统一,比如我们可以将A网站由SameSite.a.com变为SameSite.b.com,与B网站test.b.com保持一致。当然,如果采取这种方法的话,需要重新申请域名,并且原有的域名都需要重定向到新域名。
方案二:升级https
SameSite设置
A网站的请求中,cookie的设置应该带有Secure; SameSite=None这两个属性
域名升级https。
你可能需要对项目进行整体改造,比如将所有http的请求替换为https。
特别注意:
- SameSite=None需要只对chrome80以上版本进行设置,原因在于chrome51-chrome66以及其他某些浏览器不接受SameSite=None 。
- 如果网站存在http与https同时使用的情况,需要对此做兼容,只有https的时候才设置Secure;SameSite=None。原因在于当Secure设置为true时,表示创建的 Cookie 会被以安全的形式向服务器传输,也就是只能在 HTTPS 连接中被浏览器传递到服务器端进行会话验证。
最后
即使我们此次不设置SameSite为Strict或者Lax,我们也应该思考如何去预防CSRF攻击,因为SameSite设置为None的话,意味着第三方网站能发送携带cookie的请求,就如文章一开始举例的CSRF攻击一样。
小结
我们首先介绍了SameSite属性产生的背景以及为何chrome要做此次SameSite默认策略的升级,然后讲解了SameSite对应的三个属性具体限制了哪些第三方cookie,最后举了一个chrome此次升级造成系统异常的案例,给出了具体的解决方案。
chrome一直如此关注安全问题,逼迫着我们做系统改造升级,我们也应该反思,多做一些工作来提高我们系统的安全性。