CSRF攻击
- CSRF攻击又名跨站伪造请求, 是一种利用浏览器cookie机制发送伪造的请求来达到侵害用户信息和财产安全的一种网络攻击方式。
- CSRF触发时,用户会访问某第三方网站A,网站A的代码中会向某网站B发起请求,由于访问的是网站B的接口,所以浏览器会带上网站B已经保存的登录状态,网站A就达成了模拟用户操作的目的
- CSRF攻击不会获取Cookie,但是能利用浏览器的特性去使用cookie
同站与同源的差别
- 如果具有同样的二级域名则认为是同站(same-site),但是同站不一定同源,A.test.com和B.test.com就是不同源的但是同站(same-site, cross-origin),
浏览器的同源策略
- 浏览器会分辨发起请求的域名和服务器域名是否是同源的,如果不是同源则可能会阻止js对响应的数据就行下一步操作
- 浏览器并不会阻止请求的发送,因为需要服务器去判断是否使用同源策略
- 服务器可以通过设置响应头的
Access-Control-Allow-Origin
字段去规避同源策略
浏览器的同源策略和CSRF攻击
- 浏览器的同源策略并不能规避CSRF攻击,因为浏览器并不会阻止请求的发送,只会阻止响应的接收
- 即使服务器没有规避同源策略,但是依然会处理请求,只不过浏览器不允许接受响应数据而已
阻止CSRF攻击
- 阻止CSRF攻击的方式一般由三种,其根本方法在于识别发送请求的网站 到底是不是自己的网站
- 根据Referer字段可以判断是否是自己的网站,Referer一般为当前的URL且不能被修改
针对通过 Referer 字段去判断请求来源是否合法是不太靠谱的,这个字段很有可能会丢失: 1.IE6、7下使用 window.location.href=url 进行界面的跳转或者 window.open,都会造成 Referer 丢失。 2.HTTPS 页面跳转到 HTTP 页面,所有浏览器 Referer 都丢失。 3.点击 Flash 上到达另外一个网站的时候,Referer 的情况就比较杂乱,不太可信。 可以附加使用于判断请求来源,但是仅通过该字段进行判断是不太靠谱的,如果请求头丢失该字段,则服务端无法判断当前请求来源,无法校验请求是否合法。
- Origin也可用于判断是否是自己的网站但同样存在可能丢失该字段的问题
- token校验,可以将生成的一段token放在HTML表单中,在发送请求的时候带上这段token来达到判别是否是跨域请求的目的
Token防护策略的方法
- 将token输出到页面中,对于前后端不分离的页面,可以直接由后端将token添加到页面中,可以利用input表单的hidden方式来设置
<input id="token" name="token" type="hidden" value="xm234jq">
,然后在请求时用js获取该参数并在请求参数中带上该字段。
- 对于前后端分离的页面可以在登录成功的响应中返回token,并由前端保存在
localStorage
中,每次请求接口时获取token并带上token
- 后端判断token有无且是否过期
跨站策略
- samesite策略同样是防止CSRF的方法,是由浏览器的提供的,chrome很早就推出了cookie的SameSite属性来限制第三方cookie,但是大家伙都不理不睬。所以chrome干脆一不做二不休,在chrome80版本以后默认把cookie的SameSite属性设置为Lax,以此来对第三方cookie做一些限制,这样就能大大地降低被CSRF攻击的风险了。
- Samesite的三种模式对于cookie的禁止程度
- 所以浏览器一定程度上帮你规避了CSRF的风险,但是也造成了一些麻烦,当你需要跨站访问接口的是否反而是不行了
解决同站策略带来的问题
当你在本地开发时,如果向线上的服务器发送请求,首先会遇到的就是同源策略的问题,这个是老问题了,解决的方式都类似,在服务器响应头中添加
Access-Control-Allow-Origin
去规避同源策略,具体这里就不具体说了而遇到的第二个问题就是同站策略,这是就需要服务器在响应头中添加Same-Site字段,如果你使用的框架支持是最好的,但是有些框架并不支持,这时候最好是使用nginx提供的配置来添加same-site: None字段,同时需要添加secure字段且保证是https请求。
该字段最好在测试服务器使用,正式服务器使用会带来安全问题。
参考文章: