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 攻击而拒绝该请求。
- 后端随机生成一个 Token 并保存在 Session 中,并把这个 Token 返回给前端
- 前端发起请求时把 Token 带到请求数据或者请求头中发送给后端
- 后端校验前端传入的 Token 和后端 Session 中的 Token 是否一致
NodeJS 下的 Token 验证
NodeJS 不具备 Session 的功能,可以借助 Cookie 来传送 Token
- 后端随机生成一个 Token,基于这个 Token 利用 SHA-56 等散列算法生成密文
- 后端将 Token 和生成的密文都设置为 Cookie,并返回给前端
- 前端发请求时,从 Cookie 中获取 Token,把 Token 加入请求数据或请求头
- 后端校验 Cookie 中的密文和前端请求带过来的 Token,进行正向散列验证