Cookie SameSite属性介绍及其在ASP.NET项目中的应用
一、Cookie SameSite属性介绍
就像大家已经知道的,一旦设置Cookie之后,在Cookie失效之前浏览器会一直将这个Cookie在后续所有的请求中都传回到Server端。我们的系统会利用Cookie这个特性做很多事情,但通常我们会在Cookie中存放加密的用户身份,在Server端根据此身份检验用户是否有权限进行相应操作。
发送Cookie时,以往浏览器并不检测当前地址栏上的域(Domain)是不是和这个Cookie所属的域是否相同。恶意用户会利用这个问题巧妙设计一个站点,诱导用户点击从而造成跨站点请求伪造攻击(CSRF)。
为了解决这个问题,国际互联网工程任务组(IETF)提出了一个SameSite的草稿标准,Chrome 51开始支持此功能,但从Chrome 80 Stable版本开始启用一个较严格(Lax)的默认设置。
二、什么是跨站点请求伪造攻击(Cross-Site Request Forgery Attack,CSRF)
CSRF攻击简单而言就是恶意用户通过巧妙伪造请求从而盗用合法用户的身份进行恶意操作。
比如你开发了一个非常厉害的系统,系统中某些操作只有特定的人登录之后才有权限使用:
yourdomain.com/snap
[Authorize("Thanos")]
[HttpPost]
public ActionResult Snap()
{
///dangerous, will destroy the world.
}
因为系统要检验身份和权限,除非恶意用户能破解登录系统以Thanos身份登录,否则是没有办法调用这个方法的。
但是恶意用户可以伪造一个像下面这样的页面,恶意用户通过发邮件或者通过跨站点脚本攻击(XSS)等方式诱导具有权限的用户点击页面上的某些Button。如果具有权限的用户刚好已经登录,一旦点击按钮,系统则会以这个用户的身份触发上面危险的操作Snap()。
malicioususer.com/fancypage
...
<form action="yourdomain.com/snap">
<input type="Submit" value="This is cool, click me"/>
</form>
...
当然,微软 ASP.NET是通过AntiForgeryToken来解决这个问题,不过这个不是这篇blog讨论的主题。
三、Cookie的SameSite属性
为了解决上面到的Cookie的安全问题,Chrome从版本51增加了一个新的Cookie属性SameSite, 以控制Cookie是否能在跨站点的情况下传送。
Cookie所属的域名如果和浏览器地址栏中的域名不一致,则认为是跨站点。另外,当你的站点被iframe嵌在第三方站点时也被认为是跨站点。
这个属性有三个属性值:
None
如果你需要在任意跨站点情况下都使用某个Cookie,则需要将这个Cookie的SameSite设置为None. 但这里需要注意的是一定要同时设置Cookie的Secure,也就是需要使用https访问时才能关闭SameSite功能. 如果没有标明为secure, Chrome 80及以上会拒绝设置这个Cookie。
set-cookie: samesite=test; path=/; secure; SameSite=None
Strict
顾名思义,这是严格模式,就是在任何情况下都不允许跨站点发送Cookie。
这个设置显然是可以解决上面所提到的CSRF问题。因为当访问 malicioususer.com/fancypage 页面时,当前域是 malicioususer.com, 但user点击button提交时的action是指向另外一个域 yourdomain.com,这是两个不同的域,浏览器将不回传yourdomain.com下面的Cookie。这会极大的提高我们系统的安全性。
但这个严格模式也限制了一些被认为是安全的链接操作,比如:
- 你先登录了公司HR系统,假设该系统将所有Cookie的SameSite都设置为strict.
- 你用Web邮件系统收到了要求你到HR系统做审批操作的邮件,这封邮件带了一个link,直接链接到HR系统中审批的页面;
- 你点击这个link,但因为Cookie被设置为Strict模式,当到达审批页面时,HR系统没有收到任何Cookie,这时会认为你没有登录,而直接跳转到登录页面。在要求不是非常严格的情形下,可以认为这不是我们所期望的行为。因为只是跳到链接指向的页面并不是像POST操作修改数据。这需要通过下面的Lax属性解决这个问题。
Lax
Lax是比Strict稍宽松的模式,如果我们要允许跨站点链接传Cookie或FORM用GET Method提交时跨站点传Cookie, 则可以将这些Cookie的SameSite设置为Lax. Lax在Chrome 80成为默认设置,Lax既防止了CSRF也确保了正常的跨站点链接,是适合大多数站点的,可以解决上面HR系统安全中提到问题。
如果你的站点需要被iframe嵌套在第三方站点,这时你还是需要将Cookie设置为None。
这里也想到一点是,如果你的MVC Action只期望接受POST方法,那么一定要加上HttpPost Attribute,以避免造成意外的安全问题。
四、浏览器兼容性
如下图示目前主流浏览器都已经支持SameSite,虽然 IE 11不支持,但我测试之后发现这个Cookie本身还是没有丢失,只是缺失了安全保护功能。
https://developer.mozilla.org/en-US/docs/Web/HTTP/headers/Set-Cookie#Browser_compatibility
五、如何修改ASP.NET程序
下面总结的步骤是适用于基于ASP.NET开发的系统。微软官方白皮书对这些属性设置做了详细的说明,也可以参考官方白皮书。
.NET Framework 4.7.2 或4.8才开始支持SameSite, 在HttpCookie增加了SameSite的属性。所以需要安装.NET Framework 4.7.2以上SDK, 并且需要安装开发电脑和服务器上。
安装 Windows 2019/11/19累积更新补丁,请见KB Articles that support SameSite in .NET Framework,也需要安装在开发电脑和服务器上。没有安装这个补丁之前,如果SameSite为None, .NET Framework并不输出这个属性到Broswer, 但Chrome 80及以后将未设置默认为Lax,因此造成不一致的行为,所以需要安装这个补丁以明确输出None。
在Chrome地址栏输入: chrome://flags/, 将下面两项设置为Enabled。开启这两项设置是因为不是所有的Chrome都默认启用了这两项设置,Chrome只是在逐渐将这两项开启到Chrome的user. 所以开发时为了重现问题,最好是显式开启。
chrome://flags/#same-site-by-default-cookies
chrome://flags/#cookies-without-same-site-must-be-secure
修改项目文件属性, Target framework 4.7.2 或4.8。
根据需要修改web.config对Cookie的SameSite设置。
<configuration>
<system.web>
<httpCookies sameSite="[Strict|Lax|None|Unspecified]" requireSSL="[true|false]" />
<anonymousIdentification cookieRequireSSL="false" /> <!-- No config attribute for SameSite -->
<authentication>
<forms cookieSameSite="Lax" requireSSL="false" />
</authentication>
<sessionState cookieSameSite="Lax" /> <!-- No config attribute for Secure -->
<roleManager cookieRequireSSL="false" /> <!-- No config attribute for SameSite -->
<system.web>
<configuration>
修改说明:
httpCookies节点中的sameSite设置会影响系统中所有未指定sameSite Cookie的值, 但不覆盖forms/sessionState中设置的SameSite属性。
forms authentication的sessionState的默认Lax模式应该能满足常规需要, 并且保证网站的安全.
确实需要接受跨站点Cookie, 比如你的网站会嵌套在第三方网站的iframe里面,则需要将相关的Cookie 的SameSite改为None。需要注意的是为None的时候必须要将requireSSL改为true:
<configuration>
<system.web>
<httpCookies sameSite="None" requireSSL="true" />
<authentication>
<forms cookieSameSite="None" requireSSL="true" />
</authentication>
<sessionState cookieSameSite="None" />
<roleManager cookieRequireSSL="false" />
<system.web>
<configuration>
Cookie的SameSite都设置为None之后,需要防范CSRF. ,比如使用AntiForgeryToken。
如果某些Cookie需要使用与web.config中配置的不同SameSite属性,只需要在设置Cookie的时候明确指定其值.
var cookie = new HttpCookie("samesite", "test");
cookie.SameSite = SameSiteMode.None;
cookie.Secure = true;
Response.Cookies.Add(cookie);
因为有些老的浏览器并不支持SameSite这个属性,直接输出这个属性会造成老的浏览器忽略这个Cookie而造成Cookie丢失,请见已知的兼容问题. 如果确实需要支持这些老的浏览器,则需要根据user agent来检测浏览器,对于不支持SameSite的浏览器,我们需要将SameSite设置为(SameSiteMode)(-1).
private void CheckSameSite(HttpContext httpContext, HttpCookie cookie)
{
if (cookie.SameSite == SameSiteMode.None)
{
var userAgent = httpContext.Request.UserAgent;
if (BrowserDetection.DisallowsSameSiteNone(userAgent))
{
cookie.SameSite = (SameSiteMode)(-1);
}
}
}
BrowserDetection.DisallowsSameSiteNone()这个方法请见SampleSiteSupport.cs.
对于ASP.NET Core应用,微软也提供了详细的解决方案。
六、如何排查SameSite问题
SameSite默认为Lax已经从Chrome 80 Stable正式开始灰度启用,如果一个Cookie SameSite未指定,将会被默认为Lax,这可能会造成网站在某些情况下不能正常工作。
Chrome Developer Tools专门为SameSite问题提供了一个检测工具,在Network tab下有一个选项"Only show requests with SameSite issues". 找到有问题的request之后,可以在Response Headers下面找到哪个Cookie有问题。如下图示,因为我设置了SameSite为None,但没有设置Secure,所以Chrome会拒绝这个Cookie.
set-cookie: samesite=test; path=/; SameSite=None
在调试的时候如果有些跳转操作,为了看到跳转前后的请求记录,可以勾中Preserve log
七、参考
Cookies default to SameSite=Lax
Reject insecure SameSite=None cookies
Work with SameSite cookies in ASP.NET
Work with SameSite cookies in ASP.NET Core
作者:吴秀祥
2020/3/28
Cookie SameSite属性介绍及其在ASP.NET项目中的应用的更多相关文章
- win7,vs2010,asp.net项目中修改外部js文件,在调试时加载的还是旧文件
win7,vs2010,asp.net项目中修改外部js文件,在调试时加载的还是旧文件 我杀过 w3wp.exe和asp.net_state的进程,重启 iis admin的服务,都还是不行. 只是把 ...
- ASP.NET项目中引用全局dll
在ASP.NET项目中,有些dll是全局dll,也就是说,没有放在单个项目的引用中.它们一般存放在如下目录C:\Windows\assembly中 这个时候,我们需要在单个项目中引用他们,应该如何做呢 ...
- 如何在ASP.NET 项目中使用Silverlight页面
闲来无事,想写个网站玩玩,比较懒,不想写太多的样式来美化,看中了Silverlight,样式布局比较省事,但是又不想全部都用Silverlight 来写,所以才有此一文. 其实Silverlight最 ...
- VS的ASP.NET项目中cshtml关键词出错 红线,当前上下文中不存在名称
[参考]VS的ASP.NET项目中cshtml突然出错,当前上下文中不存在名称“ViewBag” 原因:web.config 配置错误 这种情况是因为两个web.config文件版本不匹配,需要进行修 ...
- selenium2 WebDriver 在asp.net项目中的应用
selenium2 WebDriver是一款跨平台的 自动化测试工具,它可以操纵浏览器,模拟用户行为,非常方便用户进行自动化测试. .net项目使用它,首先要通过 Visual Studio 的 nu ...
- 在ASP.NET项目中使用CKEditor +CKFinder实现图片上传功能
前言 之前的项目中一直使用的是FCKeditor,昨天突然有个想法:为什么不试一下新的CKEditor呢?于是花了大半天的时间去学习它的用法,现在把我的学习过程与大家分享一下. 谈起FCKeditor ...
- ASP.NET项目中使用CKEditor +CKFinder 实现上传图片
CKEditor是什么 CKEidtor是一个在线富文本编辑器,可以将让用户所见即所得的获得编辑在线文本,编辑器或自动将用户编辑的文字格式转换成html代码. 在ASP.NET工程中添加CKEdito ...
- 向asp.net项目中添加控件AspNetPager
1.打开项目,把.dll文件放入项目中: 2.在工具栏中添加一个自定义选项卡
- 在ASP.NET项目中使用CKEditor
CKEditor是什么 CKEidtor是一个在线富文本编辑器,可以将让用户所见即所得的获得编辑在线文本,编辑器或自动将用户编辑的文字格式转换成html代码. 在ASP.NET工程中添加CKEdito ...
随机推荐
- python自动化测试技术-Allure
文末有源码 大部分人可能做的是爬虫和web,数据分析方面的工作,今天分享个在自动化测试领域python能做什么样的事情,比如下方,是用python+pytest+allure生成的精美自动化测试报告, ...
- Mac系列萎靡 大棒能否敲醒苹果?
大棒能否敲醒苹果?" title="Mac系列萎靡 大棒能否敲醒苹果?"> iPhone在智能手机市场中的一骑绝尘,不断将苹果推向神坛位置.即使新品更新幅度 ...
- Thinkpad E40热键不能使用解决办法
Thinkpad E40 0578M68笔记本电脑安装windows7 64bit和联想官网驱动后,键盘最上面一排热键中,除了静音.减小音量和增大音量之外,其余的热键均不可用,解决办法: 到联想官网下 ...
- FPGA小白学习之路(4)PLL中的locked信号解析(转)
ALTPLL中的areset,locked的使用 转自:http://www.360doc.com/content/13/0509/20/9072830_284220258.shtml 今天对PLL中 ...
- SpringBoot图文教程8 — SpringBoot集成MBG「代码生成器」
有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1「概念+ ...
- Android 开发技术周报 Issue#270
新闻 Play Store应用更新:换主题不需要再到系统设置了 新证据表明谷歌Fuchsia系统已进入"狗粮"阶段 即将邀请用户测试 谷歌I/O 2020 开发者大会如期举行 MW ...
- tfgan折腾笔记(二):核心函数详述——gan_model族
定义model的函数有: 1.gan_model 函数原型: def gan_model( # Lambdas defining models. generator_fn, discriminator ...
- GO - if判断,for循环,switch语句,数组的使用
1.if - else if - else的使用 package main import "fmt" func main() { // 1.简单使用 var a=10 if a== ...
- kafka知识整理
title: kafka知识整理 date: 2019-06-18 10:59:46 categories: MQ tags: kafka --- 转载自:https://www.cnblogs.co ...
- 点云3d检测模型pointpillar
PointPillars 一个来自工业界的模型.https://arxiv.org/abs/1812.05784 3D目标检测通常做法 3d卷积 投影到前平面 在bird-view上操作 处理思路依然 ...