什么是CSRF?
- CSRF : cross-site-request-forgery:跨站请求伪造
-
攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。这利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
-
Cookie 往往用来存储用户的身份信息,恶意网站可以设法伪造带有正确 Cookie 的 HTTP 请求,这就是 CSRF 攻击。
如何防止CSRF攻击?
-
1.http头部的
referer
字段会标明请求来源哪个网站,比较referer
的地址和请求地址,是属于同一个域名,还是不同域名(第三方网站),来判断是否 CSRF 攻击。如果二者不是相同域名,就不通过请求申请。- 局限性:
- 完全依赖于浏览器发送正确的referer 字段,但无法保证来访浏览器的具体实现。
- 无法保证浏览器是否存在安全漏洞,对referer造成影响。
- 存在攻击者攻击浏览器,篡改 referer 字段。
- 局限性:
-
2.添加校验
token
。前端发出请求时,加入从后端返回的token字段的值(不能存储在cookie中、攻击者无法伪造的值
),如果token不正确,不通过请求。 -
3.设置 cookie 的
SameSite
属性Strict
: 完全严格模式,完全禁止第三方cookie。跨站点时,不会发送cookie。只有当前网站的URL和请求目标地址一致时,才会发送。- 太严格,用户体验不好。例如,在已登录GitHub的情况下,从别的网站点击GitHub链接地址跳转到GitHub,因为不会发送GitHub的cookie,跳转到GitHub网站上总是显示未登录状态。
-
Set-Cookie: CookieKey=CookieValue;SameSite=Strict;
Lax
: 相对严格模式,大多数情况下不发送 cookie,导航到目标网址的 Get 请求除外。- 发送cookie情况:
请求类型 示例 正常情况 Lax 链接 <a href="..."></a>``<a href="..."></a>
发送 Cookie 发送 Cookie 预加载 <link rel="prerender" href="..."/>
发送 Cookie 发送 Cookie GET 表单 <form method="GET" action="...">
发送 Cookie 发送 Cookie POST 表单 <form method="POST" action="...">
发送 Cookie 不发送 iframe <iframe src="..."></iframe>
发送 Cookie 不发送 AJAX $.get("...")
发送 Cookie 不发送 Image <img src="...">
发送 Cookie 不发送 Set-Cookie: CookieKey=CookieValue;SameSite=Lax;
None
- Chrome 计划将
Lax
变为默认设置。网站可选择显示关闭SameSite
属性,将其设为None
。不过,前提是必须同时设置Secure
属性(cookie只能通过 HTTPS 协议发送),否则无效。 - 下面设置无效
Set-Cookie: widget_session=abc123;SameSite=None
- 下面设置有效
Set-Cookie:widget_session=abc123;SameSite=None;Secure
- Chrome 计划将
参考链接
Using the Same-Site Cookie Attribute to Prevent CSRF Attacks
SameSite cookies explained
Tough Cookies, Scott Helme
Cross-Site Request Forgery is dead!, Scott Helme
阮一峰的网络日志:Cookie 的 SameSite 属性
(完)