我正在致力于将安全的CSRF令牌实现到我的NodeJS后端&React前端应用程序中,该应用程序使用express-sessions.我已经创建了this module来生成、验证和存储Redis中的CSRF令牌,包括一些额外的安全性,例如每个令牌单独的秘密以实现安全漏洞、每个功能的令牌,以及对同一功能的多个选项卡(即令牌ID和密钥)的支持.

我读到CSRF令牌是加密的,只有服务器知道密钥,所以当浏览器将令牌发送到服务器时,服务器可以通过只有服务器知道的密钥进行验证.My question is why are they encrypted

根据我的理解,如果攻击者设法窃取了加密的令牌,则加密是无用的,因为当他们提交带有令牌的请求时,服务器将对其进行验证,因为它本质上是相同的加密令牌.如果是这样的话,将令牌也存储在服务器上并判断客户端提交的令牌是否匹配不是更好的性能吗?(当然,在比较中考虑了计时攻击)

谢谢

推荐答案

CSRF令牌通常不会加密.在一个用于在普通Web应用程序中安装同步器令牌模式的教科书实现中,CSRF令牌只是一个足够大的随机值,存储在服务器上,也在表单生成时提供给客户端.然后,客户端可以将其与表单一起发回,以证明它发送的表单实际上是由服务器生成的,而不是其他人.(即使在双重发布等其他模式的情况下,作为标头字段和Cookie发送的令牌在基本情况下也只是一个随机令牌.)

然而,有两件事需要注意.

同步器令牌模式(classic 的CSRF令牌)需要服务器查找.如果有用户会话,这并不是什么大问题,但情况并不总是如此,一些应用程序被设计为无状态的.在这种情况下,您不能只拥有一个随机令牌,因为您无法在不判断服务器端状态的情况下决定它是否有效.

另一件需要注意的事情是,如果令牌包含一些关于客户端的信息,您实际上可以进一步提高安全性.例如,如果CSRF令牌以某种方式与客户端绑定(例如,如果它在更简单的实现中与当前客户端IP地址相关联),那么以某种方式窃取CSRF令牌就没那么有用了.同样,您可以将此附加信息存储在服务器端,但这也是一些应用程序希望避免的,以使负载平衡等事情更容易.

因此,它归结为无状态CSRF令牌,您只需按原样进行判断,而无需在后端进行状态(数据库)查找.

您可以做的(以及一些框架为您所做的)是,它们创建一个 struct 化令牌,其中嵌入了一些数据,并使用只有服务器知道的密钥对其进行加密.然后,服务器将其作为CSRF令牌发送,并期望在状态更改请求时将其接收回来.当它收到它时,服务器不需要数据库查找,它只需解密令牌,并查看它是否是服务器创建的有效令牌.

请注意,纯粹出于这个目的,您实际上不需要加密,更适合的加密原语将是消息验证码,因为您只关心令牌的真实性,即.是服务器自己创建的,而不是其他人.然而,某些框架包含在令牌中的数据通过加密(以及通过适当的经过身份验证的加密算法进行隐式消息身份验证)进一步得到多次保护.但在一个非常基本的实现中,您实际上可以只将时间戳和用户ID与HMAC一起作为无状态的CSRF令牌(但包括更多信息,甚至可能是关于所生成的表单字段的信息将进一步提高安全性).

因此,简而言之,未加密的随机令牌被认为足以用于CSRF,在双重发布的情况下,它们也可以是无状态的(由于同源策略,攻击者不能将相同的随机令牌作为Cookie和报头发布到不同的来源).但如果需要,加密的、信息更丰富的令牌可以提供更多的安全性,甚至可能在一定程度上减轻被盗的CSRF令牌威胁.

Node.js相关问答推荐

如果非SQL函数在事务内部运行失败,PG-Promise事务会回滚吗?

Node.js PNG缓冲区获取未知图像格式错误

如何在ejs模板中使用循环显示多个结果?

Nestjs重写子类dto nodejs中的属性

为什么 mongoose 没有常规数组方法

GitLab 依赖扫描需要源代码中的 package-lock.json 才能执行

NodeJS:zlib.gzipSync 在不同平台上给出不同的明文输出

Typescript :泛型类又扩展了另一个泛型类

如何获取需要加载cheerio的网站部分数据?

使用 Nodejs 获取 Firebase 云消息传递历史记录

BrowserRouter 无法渲染组件

如何使用填充在mongoose 上保存新数据

简单的 Node js 程序但执行顺序似乎不同?

运行摩卡+伊斯坦布尔+通天塔

Node.js 中空函数的简写

Node.js 应用程序有周期性的缓慢和/或超时(不接受传入的请求)

为什么数组上的js映射会修改原始数组?

node.js 模块和函数中this的含义

安装 node 包时可以使用自定义目录名称而不是node_modules吗?

Route.get() 需要回调函数,但得到对象未定义