使用双重提交防止 CSRF 的唯一方法是在 cookie 中发送 nonce。如果您在 HTTP 响应正文中发送它,在某些情况下,它可能会被发送跨域请求的脚本解析出来(如果您允许该页面使用 CORS),这会破坏防止 CSRF 的整个目的。这个想法是域 X 上的脚本无法获取域 Y 上 cookie 的值,这是 Web 安全性的主要支柱之一。
使用 HTTPOnly cookie,您将无法使用最常用的方法来防止 CSRF - 即通过 cookie 双重提交 nonce 和能够读取 cookie 的页面上的脚本。以下是该技术的工作原理:
1) 为会话生成一个存储在服务器上的nonce值。它可能是会话 ID 本身,也可能是存储在与会话关联的数据中的东西。
2) 通过不带HTTPOnly的 cookie 标头将其发送到客户端,让一些 Javascript 抓取并存储它(例如短期或在 sessionStorage 中)
3) 与您希望保护免受 CSRF 影响的每个请求一起提交。请求将在 cookie 中包含 sessionId,在请求正文或 URL 查询字符串中也有这个 nonce(例如,对于 GET 请求)。如果您担心日志中的 nonce 或其他内容,您可以使用Web Crypto 使用此 nonce 使用 HMAC 对请求有效负载进行签名
4)服务器会查找会话数据,检查nonce是否不匹配,抛出错误并生成另一个nonce并发送到cookie中。确保仅在 cookie 中发送随机数!
不幸的是,许多“安全审计”工具开始标记未标记 httpOnly 的 cookie,并建议添加此标记。可悲的是,这面旗帜比无用更糟糕:它是安全剧院。
我说的只是 httpOnly 标志。这比无用更糟糕,因为它让你认为你躲过了某种子弹,而实际上同样的攻击仍然可能发生:攻击者需要编写一个脚本来将 cookie 发送到他们的服务器,所以他们不妨该脚本在您的授权会话的上下文中执行实际请求,就像他们拥有您的 cookie 时那样。他们会提前写好剧本。没有真正的攻击者会在凌晨 3 点坐在那里发出请求,因为他们的受害者最终激活了一个向他们发送 cookie 的脚本。更有可能的是,该脚本已经预先编程以执行它需要执行的操作。如果不存在 httpOnly cookie,人们会更关心清理他们的 Javascript 输出以防止 XSS,