1

什么是CSRF

跨站请求伪造(Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web上执行非本意的操作的攻击方法。

简单来说,就是冒用你的登录信息,以你的名义发送恶意请求。

原理

  1. 用户A登录了自己常用的网站 www.yinhang.com, 登录成功后,cookie中会包含A的登录信息
  2. 骗子 利用广告或者链接等诱导你打开网站 www.jiamao.com。该网站中会利用form表单或者其他方式,向网站 www.yinhang.com 发送请求,网站的接口请求格式一般很容易获取到,例如 www.yinhang.com/api/zhuanzhang?account=A&count=10000&to=pianzi 发送的请求会自动携带上www.yinhang.com的cookie信息,即你的身份验证信息
  3. 服务器端在收到请求后,检验身份信息是正确的,然后整个攻击就完成了

常见解决方案

referer首部

在request header中,有个referer字段,表明请求的来源,服务端可以通过这个字段判断是否是在合法的网站下发送的请求。

缺陷:Referer的值是由浏览器提供的,不同的浏览器实现不同,无法确保某些浏览器是否有安全漏洞,导致可以自行修改Referer字段

表单 token检测

由服务端生成一个token,返回给前端,在每次发送请求中,在参数中额外参加一个参数,例如 _csrf_token , 服务端每次校验时对比 _csrf_token 与服务端存储的值。

fetch(path, {
    ...otherParam,
    _csrf_token: 'token_value'
});

或者服务端返回的表单页面中隐藏 _csrf_token值

<form method="POST" action="/upload" enctype="multipart/form-data">
    <input name="_csrf_token" value="{{由服务端生成}}" style="display: none" />
    用户名: <input name="name" />
    <button type="submit">提交</button>
</form>

缺陷: 需要手动传递参数值,比较冗余麻烦,额外的参数字段也没有业务意义

header中增加csrf_token

由后端生成csrf_token设置在cookie中, 前端获取到token后设置在header中,可以统一在封装request方法时写入,例如


let csrfToken = Cookies.get('csrfToken');

$.ajaxSetup({
  beforeSend: function(xhr, settings) {
      xhr.setRequestHeader('x-csrf-token', csrfToken);
  }
});

留个思考,csrf一般都是跨网站的,按理应该都会有跨域限制,所以请求是怎么发出去的呢。

猜想1: 网站使用了cors跨域访问,但对域名未加限制
猜想2: 某些浏览器并不能对跨域做良好的限制


晴天
7 声望3 粉丝