OAuth2.0服务器堆栈如何使用状态来防止CSRF? for draft2.0 v20

时间:2012-06-17 13:04:34

标签: php oauth oauth-2.0 oauth-provider

我正在使用PHP library for OAuth2.0 v20

在draft20中,有一个mention of the use of state to prevent CSRF

到目前为止,我自己的实现此PHP库的Web应用程序允许以下内容:

  1. 3 legged authentication using Authorization Code Request
  2. 2 legged authentication using Resource Owner Credentials Grant
  3. a Request that refreshes an access token
  4. 我是否需要在上述所有3种情况下使用状态?

    如果是这样,“状态”的一个好例子是什么?

    是什么让一个好的“国家”?

    任何理想的长度?任何最小长度?任何最大长度?

    任何理想的化妆品?字母数字包括大写?

3 个答案:

答案 0 :(得分:34)

通过示例CSRF漏洞可能会有所帮助,以便了解状态参数如何减轻此类攻击。在此示例中, Mallory 攻击者 Alice 受害者

攻击

  1. Mallory访问了一些客户网站,并开始授权该客户使用OAuth访问服务提供商

  2. 客户要求服务提供商授权代表Mallory代表请求访问权限

  3. Mallory被重定向到服务提供商的网站,在那里她通常会输入用户名/密码以授权访问

  4. 相反,Mallory陷阱/阻止此请求并保存其网址

  5. 现在,Mallory不知何故让Alice访问该网址。如果Alice使用自己的帐户登录服务提供商,则她的凭据将用于颁发授权码

  6. 授权代码交换访问令牌

  7. 现在客户端上的 Mallory 帐户有权访问服务提供商上的 Alice 帐户

  8. 那么,我们如何使用state参数来阻止这种情况?

    预防

    1. 客户端应该创建一个基于原始用户帐户(例如,用户的会话密钥的哈希)的值。只要它的唯一并使用一些关于原始用户的私密,不可饶恕的信息生成它并不重要。

    2. 此值在上面第三步的重定向中传递给服务提供商

    3. 现在,当Mallory让Alice访问保存的URL时(上面的第五步),该URL包含使用Mallory的会话信息生成的state参数

    4. 授权代码将与 Alice的会话一起发送并发送回客户端以及Mallory的state参数

    5. 客户端根据 Alice 会话信息生成新的state值,并将其与从{em>发回的state值进行比较对服务提供商的授权请求。此值与请求中的state参数不匹配,因为state值是基于 Mallory的会话信息生成的,因此会被拒绝。

    6. 攻击者无法为任何特定用户生成状态值,因此欺骗用户访问其授权URL无效。

答案 1 :(得分:16)

仅使用授权码流程进行#1 - 3条腿授权

当您的应用程序交换访问令牌的授权代码时,您希望确保导致所提供的授权代码的OAuth流实际上是由合法用户启动的。因此,在客户端应用程序通过将用户重定向到提供程序来启动OAuth流之前,客户端应用程序会创建一个随机状态值,并通常将其存储在服务器端会话中。然后,当用户完成OAuth流程时,您检查以确保状态值与存储在用户服务器端会话中的值匹配 - 这表示用户已启动OAuth流程。

状态值通常应该是伪随机不可评估的值。可以使用PHP中的rand()函数生成一个简单的值作为int,尽管您可能会变得更复杂以提供更好的保证。

状态的存在是为了防止像我这样的事情通过电子邮件向您发送链接,其中包含我的帐户的授权代码,您点击它并且应用程序将所有数据推送到我的帐户中,这是您不知道的。

OAuth 2.0威胁模型文档中提供了一些其他信息: http://tools.ietf.org/html/draft-ietf-oauth-v2-threatmodel-00

特别参见CSRF保护部分: http://tools.ietf.org/html/draft-ietf-oauth-v2-26#section-10.12

答案 2 :(得分:-3)

因为“状态”只是一个随机字符串,所以制作这样的东西应该可以解决问题:

$state = md5(uniqid(rand(), TRUE));

请记住将其保存在会话中,以便日后查看。