将状态参数值存储在 cookie 中是否安全?

信息安全 oauth oauth2
2021-08-19 14:43:00

根据https://www.rfc-editor.org/rfc/rfc6749#section-10.12

客户端必须为其重定向 URI 实现 CSRF 保护。这通常通过要求发送到重定向 URI 端点的任何请求包含一个将请求绑定到用户代理的已验证状态的值(例如,用于验证用户代理的会话 cookie 的哈希)来实现。 客户端在发出授权请求时应该使用“state”请求参数将此值传递给授权服务器

一旦从最终用户获得授权,授权服务器将最终用户的用户代理重定向回客户端,并使用“state”参数中包含的所需绑定值。 绑定值使客户端能够通过将绑定值与用户代理的身份验证状态匹配来验证请求的有效性用于 CSRF 保护的绑定值必须包含一个不可猜测的值(如第 10.10 节所述),并且用户代理的身份验证状态(例如,会话 cookie、HTML5 本地存储)必须保存在只有客户端可访问的位置和用户代理(即受同源策略保护)。

使用安全的、HTTPOnly 的 SameSite cookie(例如,超时时间短)来存储state参数值是否安全?使用参数中的值验证 cookie 中的值state是否足以验证请求的有效性?

1个回答

使用安全的、HTTPOnly 的 SameSite cookie(比如,超时时间很短)来存储 state 参数的值是否安全?

你可以让它安全。

假设您正在编写服务器端软件(我假设您这样做,因为您提到为 cookie 设置 HTTPOnly 选项):加密服务器上的状态参数并将加密值存储在 cookie 中。(详细信息:确保使用带有随机 iv 的安全加密算法,并且不要使用 ecb 模式)。确保在服务器上保持加密密钥的安全。

为什么要加密cookie?

您必须加密状态值(或整个 cookie)有两个原因:

  1. 原则上:安全人员喜欢分层他们的安全措施。如果一个失败了,另一个仍然会保护你。即使您使用 SSL 保护您的流量,SSL 加密也可能会受到影响。例如,在我工作的地方,我们有一个内容检查防火墙,它在 SSL 上执行 MITM,因此它通过设计破坏了连接的安全性。(总而言之,这是一个非常糟糕的主意,但我相信这很常见 - 这意味着您不能指望 SSL 保护从服务器到客户端的连接。

  2. 保护来自客户端(用户代理)的状态值。如果您的客户端上有恶意软件,您不想将状态值暴露给它。可能会被偷。如果状态值是加密的,客户端软件就无法访问它,这很好。

这安全吗?

这与在 cookie 中存储会话 id 然后使用会话 id 作为服务器端数据库表的索引一样安全,因为浏览器、浏览器中的恶意 javascript 和其他任何人都不会看到任何不透明的东西, 加密 cookie 中的随机字符串,如果他们以任何方式弄乱它,它不会解密为原始状态值,这将导致状态验证失败。但是您可能想要添加一个 MAC(消息身份验证代码),并且仅在 MAC 检出时触摸 cookie 中的加密状态值,以保护您的 cookie 内容免受干预。

本地浏览器内 javascript 与服务器端处理

如果您正在编写发出 oauth 请求的浏览器 javascript,则必须格外小心(但 javascript 浏览器的安全性从根本上被破坏了;如果您有一个 javascript 浏览器应用程序执行 oauth 请求,我怀疑您能否使其真正安全 - 您可以它相当安全,但可能无法抵御坚定的对手。

验证状态参数是否足够?

使用 state 参数中的值验证 cookie 中的值是否足以验证请求的有效性?

验证状态是否足以验证 oauth 请求(回复?)取决于您使用的流程以及您在协议中的哪个步骤。

例如,如果您要取回一个 jwt id 令牌,在几乎所有情况下,您都必须验证 id 令牌以确保它是有效的并且适合您(您可以自己执行此操作或将其发送到验证端点。 jwt id 令牌经过数字签名,您必须确保签名正确、受众和您的客户端 id 匹配、令牌未过期等)。

访问令牌也是如此:例如,如果您不验证访问令牌的受众,则可能会发生不好的事情(例如,访问令牌可能用于另一个客户端......)

在某些情况下,您不需要验证令牌。当您使用 open id connect 从身份提供者获取 id 令牌并且您不通过浏览器路由请求,并通过服务器端请求从身份提供者取回 id 令牌时,我认为您可以信任 id 令牌而不进行验证。但是,我仍然总是验证,只是为了确保我不会因自己的聪明而跌倒;-)