Egg: 重新梳理 csrf

Created on 14 Jan 2017  ·  13Comments  ·  Source: eggjs/egg

https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet#CSRF_Specific_Defense

业界主要的几种方案:

强 csrf token 校验

  • 实现方案:koa-csrf
  • 优点:强校验
  • 缺点:依赖服务端状态(session),ajax 使用不方便

Double Submit Cookie(ctoken)

  • 实现方案:ctoken
  • 优点:仅弱于强 csrf token 校验,不需要服务端状态。
  • 缺点:对 ajax 使用不够友好。

指定 header

egg 方案

综合考虑,强 csrf token 校验体验不好,指定 header 方案有漏洞,可以考虑全部基于 Double Submit Cookie 方案来实现。

  1. 所有的 POST, PUT, PATCH, DELETE 等 unsafe 的方法都必须要经过校验。
  2. form 表单:ctx.csrf 从 cookie 中取而不再从 session 中取 token,不再使用 csrf token,统一到 Double Submit Cookie 方案。
  3. 不再支持 isAjax 绕过。

文档

  1. 加强说明 Double Submit Cookie 的实现原理。
  2. 前端如何使用。

    • form 表单渲染时要渲染 ctoken。

    • ajax 请求需要带上请求头。

    • ajax 请求发现没有 ctoken 时,可以自己设置一个。

  3. 如何扩展到对同一个主域的 jsonp 请求进行防范。
exports.jsonpAPI = function*() {
  // 手动校验 ctoken,前提是同域有 cookie
  this.assertsCSRF();
  yield this.service.user.create(this.request.body);
  this.jsonp = { success: true };
}
egg-security

Most helpful comment

方案不一样,是走header的不走cookie,确实比较重,不过是有标准和规范的, 认同先使用ctoken做ajax防范

All 13 comments

为什么对 ajax 请求也需要校验 csrf:

  1. 用户一旦错误的使用 cros,会暴露被跨站攻击的风险。例如 kcors 的默认配置。
  2. 如果有用户错误的解 body(或者完成这个请求根本不依赖于 body 的参数),也可能被攻击。 https://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html#csrf-protection-and-json

再提一个技术方案 https://jwt.io/ 通过约定header的

好处:

  • 支持跨域
  • 无状态,不依赖session
  • 跨终端,只需要生成token就好了
  • 标准化 jwt规范

jwt 和 ctoken 方案本质上类似吧,只是多了一层加密和校验,用来做 csrf 防范太重了

方案不一样,是走header的不走cookie,确实比较重,不过是有标准和规范的, 认同先使用ctoken做ajax防范

form 必须走 csrf 才能防住吧,form 走 ctoken 是防不住的。

明白了,form 也得提交 ctoken,然后跟 cookie 的 ctoken 校验。

那么就统一了,必须先渲染一次页面,种上 ctoken。

+1

把这个搞定应该可以发 1.0 了

https://scotthelme.co.uk/csrf-is-dead/ 今天看到这个,还是很应景的

samesite cookie我看最近死马的pr有出现过

之前刚接触egg的时候,提交表单好像就要验证cookie,然后表单中还要有一个隐藏域存放csrf值的,但是今天突然发现,好像没有了这个,是不是默认关闭了啊?

@lzq920 依旧需要,可以看文档确认一下策略。 https://eggjs.org/zh-cn/core/security.html#安全威胁-csrf-的防范

Was this page helpful?
0 / 5 - 0 ratings