CRSF 跨站脚本攻击已死,使用 Same-Site Cookies 来防范 CSRF

跨站请求伪造,也称为CSRF或XSRF,基本上永远存在。 它源于网站必须向另一个站点发出请求的简单功能。 

假设我在 https://a.com 面中嵌入了以下表单。

<form action="https://your-bank.com/transfer" method="POST" id="stealMoney">
	<input type="hidden"name="to"value="Scott Helme">
	<input type="hidden"name="account"value="14278935">
	<input type="hidden"name="amount"value="£1,000">
</form>


你的浏览器加载此页面,结果是上面的表单,然后我在页面上使用一个简单的JS提交。

document.getElementById("stealMoney").submit();


我正在伪造一个跨站点发送请求到您的银行。这里真正的问题不是我发送了请求,而是您的浏览器会发送您的 cookie。 该请求将把您当前持有的全部权限一并发送,这意味着如果您已登录到您的银行,您就向我转账了1,000英镑。 如果您没有登录,那么请求将是无害的,因为您无法在未登录的情况下转账。


之前,您的银行可以通过几种方式来缓解这些CSRF攻击:

1,转账前需要验证码

2,检查来源(Origin)

3,Anti-CSRF令牌


Chrome 51 开始,浏览器的 Cookie 新增加了一个 SameSite 属性,用来防止 CSRF 攻击和用户追踪。它可以设置三个值:Strict、Lax 和 None。


1 Strict

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

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


这个规则过于严格,可能造成非常不好的用户体验。比如,如果我提供了 https://facebook.com 的链接,并且Facebook将SameSite cookie设置为严格模式,当您单击链接到打开Facebook时,无论您是否已登录,在新标签页中打开它,从该链接访问时都不会登录到Facebook。


类似于亚马逊做的,他们有2个cookie。一种是一种“基本”cookie,可以将您识别为用户,并允许您拥有登录体验,但如果您想做一些敏感的事情,比如购买或更改帐户中的内容,则需要第二个cookie, “真正的”cookie,可以让你做重要的事情。


2 Lax

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

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


导航到目标网址的 GET 请求,只包括三种情况:链接,预加载请求,GET 表单。其他都不会发送请求,比如 GET 表单,POST 表单,iframe,Ajax,img 标签的 src 加载。所以说设置了 Strict 或 Lax 以后,基本就杜绝了 CSRF 攻击。当然,前提是用户浏览器支持 SameSite 属性。


3 None

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

下面的设置无效:

Set-Cookie: widget_session=abc123; SameSite=None

下面的设置有效:

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


这也是为什么打开 koa-csrf 的 npm 页面,提示:

参考:

https://www.npmjs.com/package/koa-csrf

https://scotthelme.co.uk/csrf-is-dead/

https://www.ruanyifeng.com/blog/2019/09/cookie-samesite.html

声明:本站所有文章和图片,如无特殊说明,均为原创发布。商业转载请联系作者获得授权,非商业转载请注明出处。
真诚赞赏,手留余香
赞赏
搜神记
765 文章
4 教程
8 项目
随机推荐
用 JavaScript 实现数字增加滚动动画
Linux netstat 命令
WordPress 获取当前主题文件夹的路径
HTML input radio 单选按钮
MySQL的外键总结
JavaScript ES6 模块
Git push 错误:Updates were rejected because the remote contains work that you do not have locally
JavaScript 对象