定义
CSRF(Cross-site request forgery)简称:跨站请求伪造。是一种利用用户已登录的身份,在用户不知情的情况下,诱导用户点击链接或访问恶意网站,发起伪造请求的方式。常见的CSRF攻击场景包括转账、修改密码、发帖等。
原理
这里的跨站请求伪造,主要是利用了cookie的特性,http是无状态的,cookie的出现是为了记录用户的登录状态,但是它不够安全,其中一个原因是cookie最初被设计成了允许在第三方网站发起的请求中携带,CSRF的攻击就是利用了这一“弱点”
比如我们在浏览器中打开 a.com 站点下的一个网页后,该页面发起请求的 URL 不一定也是 a.com 上的,可能有 b.com 的,也可能有 c.com 的。我们把发送给 a.com 上的请求叫做第一方请求(first-party request),发送给 b.com 和 c.com 等的请求叫做第三方请求(third-party request),第三方请求和第一方请求一样,都会带上各自域名下的 cookie,所以就有了第一方 cookie(first-party cookie)和第三方 cookie(third-party cookie)的区别。上面提到的 CSRF 攻击,就是利用了第三方 cookie 。
如何防御
- 尽量使用post
- 加入验证码
- referer请求头校验
- Anti CSRF Token
- 加入自定义的header
- 设置cookie的sameSite属性
因为csrf主要利用了cookie的特性,所以下面着重说明几个cookie的属性
Cookie的sameSite
Cookie 的SameSite
属性用来限制第三方 Cookie,从而减少安全风险。它可以设置三个值
-
strict
最为严格,完全禁止第三方cookie,
跨站点
时,任何情况都不会发送cookie,换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。可能带来的问题,比如说,如果你的网站是淘宝,用了 Strict 会这样:某微商在微博上发了条消息"新百伦正品特卖5折起 item.taobao.com/item.htm?id… 结果点进去顾客买不了,也就是说,这种超多用户的、可能经常需要用户从别的网站点过来的网站,就不适合用 Strict 了
-
lax(默认)
规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。
设置了
Strict
或Lax
以后,基本就杜绝了 CSRF 攻击。当然,前提是用户浏览器支持 SameSite 属性。 -
none
使用None的话,在任何情况下都会发送Cookie数据。不过,前提是必须同时设置
Secure
属性(Cookie 只能通过 HTTPS 协议发送),否则无效。
跨站和跨域
cookie 的samesite校验的是跨站,而不是跨域,那跨站和跨域有什么区别呢
- 跨域是指域名、协议、端口号三者中有一个不同就是跨域
- 跨站是指子域名不同,如果子域名相同,但是协议和端口号不同的话不属于跨站,eg:
a.jzplp.com
与b.jzplp.com
属于同站
Secure 和httpOnly
基于安全的考虑,需要给cookie加上Secure和HttpOnly属性,HttpOnly比较好理解,设置HttpOnly=true的cookie不能被js获取到,无法用document.cookie打出cookie的内容。
Secure属性是说如果一个cookie被设置了Secure=true,那么这个cookie只能用https协议发送给服务器,用http协议是不发送的