Cookie SameSite属性介绍及其在ASP.NET项目中的应用
吴秀祥 人气:0
#### 一、Cookie SameSite属性介绍
就像大家已经知道的,一旦设置Cookie之后,在Cookie失效之前浏览器会一直将这个Cookie在后续所有的请求中都传回到Server端。我们的系统会利用Cookie这个特性做很多事情,但通常我们会在Cookie中存放加密的用户身份,在Server端根据此身份检验用户是否有权限进行相应操作。
发送Cookie时,以往浏览器并不检测当前地址栏上的域(Domain)是不是和这个Cookie所属的域是否相同。恶意用户会利用这个问题巧妙设计一个站点,诱导用户点击从而造成跨站点请求伪造攻击(CSRF)。
为了解决这个问题,[国际互联网工程任务组(IETF)](https://ietf.org/about/)提出了一个SameSite的草稿标准,Chrome 51开始支持此功能,但从Chrome 80 Stable版本开始启用一个较严格(Lax)的默认设置。
#### 二、什么是跨站点请求伪造攻击(Cross-Site Request Forgery Attack,CSRF)
CSRF攻击简单而言就是恶意用户通过巧妙伪造请求从而盗用合法用户的身份进行恶意操作。
比如你开发了一个非常厉害的系统,系统中某些操作只有特定的人登录之后才有权限使用:
yourdomain.com/snap
````csharp
[Authorize("Thanos")]
[HttpPost]
public ActionResult Snap()
{
//https://img.qb5200.com/download-x/dangerous, will destroy the world.
}
````
因为系统要检验身份和权限,除非恶意用户能破解登录系统以Thanos身份登录,否则是没有办法调用这个方法的。
但是恶意用户可以伪造一个像下面这样的页面,恶意用户通过发邮件或者通过跨站点脚本攻击(XSS)等方式诱导具有权限的用户点击页面上的某些Button。如果具有权限的用户刚好已经登录,一旦点击按钮,系统则会以这个用户的身份触发上面危险的操作Snap()。
malicioususer.com/fancypage
````html
...
...
````
当然,微软 ASP.NET是通过[AntiForgeryToken](https:/https://img.qb5200.com/download-x/docs.microsoft.com/en-ushttps://img.qb5200.com/download-x/dotnet/api/system.web.mvc.htmlhelper.antiforgerytoken)来解决这个问题,不过这个不是这篇blog讨论的主题。
#### 三、Cookie的SameSite属性
为了解决上面到的Cookie的安全问题,Chrome从版本51增加了一个新的Cookie属性SameSite, 以控制Cookie是否能在跨站点的情况下传送。
Cookie所属的域名如果和浏览器地址栏中的域名不一致,则认为是跨站点。另外,当你的站点被ifame嵌在第三方站点时也被认为是跨站点。
这个属性有三个属性值:
1. **None**
如果你需要在任意跨站点情况下都使用某个Cookie,则需要将这个Cookie的SameSite设置为None. 但这里需要注意的是一定要同时设置Cookie的**Secure**,也就是需要使用https访问时才能关闭SameSite功能. 如果没有标明为secure, Chrome 80及以上会拒绝设置这个Cookie。
````html
set-cookie: samesite=test; path=/; secure; SameSite=None
````
2. **Strict**
故名思义,这是严格模式,就是在任何情况下都不允许跨站点发送Cookie。
这个设置显然是可以解决上面所提到的CSRF问题。因为当访问 malicioususer.com/fancypage 页面时,当前域是 malicioususer.com, 但user点击button提交时的action是指向另外一个域 yourdomain.com,这是两个不同的域,浏览器将不回传yourdomain.com下面的Cookie。这会极大的提高我们系统的安全性。
但这个严格模式也限制了一些被认为是安全的链接操作,比如:
1. 你先登录了公司HR系统,假设该系统将所有Cookie的SameSite都设置为strict.
2. 你用Web邮件系统收到了要求你到HR系统做审批操作的邮件,这封邮件带了一个link,直接链接到HR系统中审批的页面;
3. 你点击这个link,但因为Cookie被设置为Strict模式,当到达审批页面时,HR系统没有收到任何Cookie,这时会认为你没有登录,而直接跳转到登录页面。在要求不是非常严格的情形下,可以认为这不是我们所期望的行为。因为只是跳到链接指向的页面并不是像POST操作修改数据。这需要通过下面的Lax属性解决这个问题。
3. **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:/https://img.qb5200.com/download-x/developer.mozilla.org/en-UShttps://img.qb5200.com/download-x/docs/Web/HTTP/headers/Set-Cookie#Browser_compatibility
![Browser Compabibility](https://images.cnblogs.com/cnblogs_com/wxx/1683291/o_200328144905SameSite-Browser-Compatibility.png)
#### 五、如何修改ASP.NET程序
下面总结的步骤是适用于基于ASP.NET开发的系统。微软官方白皮书对这些属性设置做了详细的说明,也可以参考[官方白皮书](https:/https://img.qb5200.com/download-x/docs.microsoft.com/en-us/aspnet/samesite/system-web-samesite#sob)。
1. 安装 .NET Framework 4.7.2 或4.8, 需要安装在开发电脑和服务器上。
2. 安装 Windows 2019/11/19累积更新补丁,请见[KB Articles that support SameSite in .NET Framework](https:/https://img.qb5200.com/download-x/docs.microsoft.com/en-us/aspnet/samesite/kbs-samesite),需要安装在开发电脑和服务器上。
3. 在Chrome地址栏输入: **chrome://flags/**, 将下面两项设置为Enabled。开启这两项设置是因为不是所有的Chrome都默认启用了这两项设置,Chrome只是在逐渐将这两项开启到Chrome的user. 所以开发时为了重现问题,最好是显式开启。
chrome://flags/#same-site-by-default-cookies
chrome://flags/#cookies-without-same-site-must-be-secure
![Enable Chrome SameSite explicitly](https://images.cnblogs.com/cnblogs_com/wxx/1683291/o_200328144858Chrome-Enable-SameSite.png)
4. 修改项目文件属性, Target framework 4.7.2 或4.8。
![target .net 4.7.2 or above](https://images.cnblogs.com/cnblogs_com/wxx/1683291/o_200328144915target-dot-net472-above.png)
5. 根据需要修改web.config对Cookie的SameSite设置。
````xml
加载全部内容