CSRF攻击和防范

CSRF 攻击方式

CSRF 跨站请求伪造,通过诱导受害者进入第三方网站,在第三方网站中向被攻击网站发送跨站请求,利用受害者在被攻击网站已经获取的注册凭证,绕过后台用户验证,冒充用户操作。

一个典型的CSRF攻击有着如下的流程:

  • 受害者登录a.com,并保留了登录凭证(Cookie)
  • 攻击者引诱受害者访问了b.com
  • b.com 向 a.com 发送了一个请求:a.com/act=xx。浏览器会默认携带a.com的Cookie
  • a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求
  • a.com以受害者的名义执行了act=xx
  • 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作

防御方案

CSRF 有三种防御方法:

  • 用户操作限制,验证码机制
  • 请求来源限制:限制 HTTP Referer
  • Token 验证机制,请求数据字段中添加 token, 响应请求时校验其有效性

对于第一种方案,影响用户体验,第二种方案成本低,但并不能保证 100% 安全, 第三种方案是目前最合适的方案。

HTTP Referer 防御机制

在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,如果黑客要对网站实施 CSRF 攻击,他只能在他自己的网站构造请求,当用户通过黑客的网站发送请求到正常网站时,该请求的 Referer 是指向黑客自己的网站。

因此,只需要对每一个请求验证其 Referer 值,如果 Referer 是来自其他网站的话,就说明可能遭到了 CSRF 攻击,拒绝请求。

缺陷

使用验证 Referer 值的方法,就是把安全性都依赖于第三方(即浏览器)来保障,然而,每个浏览器产商对于 Referer 的实现可能会有差别,对于某些浏览器,比如 IE6 或 FF2,目前已经有一些方法可以篡改 Referer 值。

即使使用最新的浏览器,用户仍然可以设置浏览器使其在发送请求时不再提供 Referer。因为有些用户认为记录访问来源会侵犯他们的隐私。当他们正常访问网站时,网站会因为请求没有 Referer 值而认为是 CSRF 攻击,拒绝合法用户的访问。

Token 验证机制防御

CSRF 攻击完全是因为黑客可以伪造用户的请求,请求中所有的用户验证信息全部存在 Cookie 中,黑客可以再不知道这些验证信息的情况下直接利用用户的 Cookie 通过验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。

在 HTTP 头中加入自定义属性

可以在 HTTP 请求中加入一个随机产生的 token,放到自定义的属性里,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。

  1. 后端随机生成一个 Token 并保存在 Session 中,并把这个 Token 返回给前端
  2. 前端发起请求时把 Token 带到请求数据或者请求头中发送给后端
  3. 后端校验前端传入的 Token 和后端 Session 中的 Token 是否一致

NodeJS 下的 Token 验证

NodeJS 不具备 Session 的功能,可以借助 Cookie 来传送 Token

  1. 后端随机生成一个 Token,基于这个 Token 利用 SHA-56 等散列算法生成密文
  2. 后端将 Token 和生成的密文都设置为 Cookie,并返回给前端
  3. 前端发请求时,从 Cookie 中获取 Token,把 Token 加入请求数据或请求头
  4. 后端校验 Cookie 中的密文和前端请求带过来的 Token,进行正向散列验证