TAT.iAzrael OAuth 授权的 XSRF 漏洞及其修复
In Web开发 on 2012年11月23日 by view: 12,215
5

话说前段时间 OAuth2.0 授权被人找出了个漏洞,各个开放平台都有影响,导致一阵恐慌。虽然后来发现其实是夸大其后果了,但也暴露出我们对这个经常用的协议仍一知半解的现状。所以花了点时间,整理了 OAuth1.0 和 2.0 的授权流程、以及其中的隐患和修复方案,供各位同学了解。由于本人也是临阵磨刀,难免疏漏,欢迎指点。

一、OAuth 1.0

a)OAuth1.0 的授权流程为

OAuth1.0 授权流程(配图取自 http://dev.t.qq.com/)

其特点是请求 request_token 是需要传入 app key 和 app secert, 而 app secert 是不能公开的, 因此只适合于服务器端授权。同时授权时的交互步骤比较多, 不够简便。

二、OAuth 2.0

a) OAuth2.0 有两种授权方式

  1. Authorization code grant (Server Side),适合于有 server 端的应用授权
  2. Implicit grant(Client Side),适合于通过客户端访问的应用授权

b) Server Side 的流程为

OAuth2.0 Server Side 授权流程(配图取自 http://dev.t.qq.com/)

其中用户在打开的登录页, 登录授权之后得到的是授权码 (code), 之后由用户把 code 填入第三方的应用, 应用的 server 获取到 code 的之后, 由 server 向 oauth 换取 accesstoken, 之后可以把 token 保存在 server 上。

其中授权回调时 app server 返回的 state 是用来在请求 accesstoken 时, 验证这个换 token 请求是不是同一个用户发起的,授权服务器会把 state 的值原样的返回给 app server。

c) Client Side 的流程为

OAuth2.0 Client Side 授权流程(配图取自 http://dev.t.qq.com/)

其中,app 直接把用户重定向到授权服务器登录, 用户登录之后 app 就能拿到 token, 省却了跟 app server 的交互。但这里有个不太安全的地方, accesstoken 是保存在客户端的, 有泄漏的风险。 由于 oauth2。0 已经放弃了使用 app key 和 app secert 来验证请求, 而 app key 是公开的。 因此只要攻击者拿到了用户的 accesstoken, 就能调用 api。

三、OAuth 的 XSRF 攻击

a) OAuth 1.0

  1. 攻击者访问可靠的第三方站点 (aaa.com), 在该网站发起 OAuth 认证流程, 保存包含 request_token 的授权 URL1, 但不定向到该 URL1 所指的页面
  2. 把 URL1 中的 oauth_callback 参数改掉,换成攻击者自己的页面 hack1,组成新的 URL2,把该 URL2 发给受害者, 诱骗受害者点击
  3. 受害者点击 URL2 打开授权页, 发现是可靠的站点, 而不会发现有潜在的隐患, 因此会进行授权
  4. 受害者授权之后, 会回调到攻击者自己的页面 hack1,攻击者就可以从这个页面获取到已授权的 request_token 和 verifier,用这两个参数就能直接走到授权的第 5 步, 用 request_token 即可换取到 access_token, 之后就可以使用 access_token 访问受害者的数据 (个人资料、私密文章之类的) 了,如果这个网站(aaa.com)改密码的时候不用输入原密码,那么受害者的密码也会被改掉。

b) OAuth 2.0 (Server Side)

  1. 攻击者访问可靠的第三方站点 (aaa.com), 且该网站提供了绑定帐号功能, 在该网站使用攻击者自己的帐号 account1(aaa.com 上的账号)发起 OAuth 认证和绑定流程(例如绑定 qq 账号), 之后用他自己的 qq 号 qq1 登录,然后保存包含 code 的重定向 URL1, 但不定向到该 URL1 所指的页面
  2. 构造一个自动发起绑定请求的页面, 如创建一个 img,src="url1"。 然后把该页面 URL2 发给受害者, 诱骗受害者点击
  3. 受害者点击 URL2 时, 如果恰好在 aaa.com(account2)登录了, 浏览器存有 aaa.com 的登录态, 这时就自动把受害者在 aaa.com 的帐号绑定到 qq1 上了
  4. 攻击者现在只要用 qq1 登录 aaa.com, 就能访问到 受害者的数据 (个人资料、私密文章之类的,甚至也能改密码)。

c) OAuth 2.0(Client Side)

Client Side 的授权流程本身没有该问题, 不过由于 Client Side 是设计来给没有 server 的移动应用使用的, 其获取的 access_token 是保存在客户端的, 因此这里有泄漏的风险。

四、XSRF 修复

  1. 可以要求 OAuth1.0 的方式升级到 2.0, 由于 1.0 跟 2.0 的协议相差较大, 因此会有不少迁移特别是调试的工作;若保持使用 OAuth1.0,则可以限制 oauth_callback 为固定 url,不允许动态设置。
  2. 而 OAuth 2.0 (Server Side) 的方式, 可以要求 app server 必须对 state 进行验证, 从受害者发起的绑定请求, 由于他是中途进入的, app server 上并没有保存相应的 state, 这时 server 可以拒绝掉这次绑定请求。
  3. OAuth 2.0(Client Side) 并没有这个问题, 可以不用修复。 重点在如何安全的保存 access_token 上。

原创文章转载请注明:

转载自AlloyTeam:http://www.alloyteam.com/2012/11/oauth-authorization-xsrf-vulnerability-and-its-repair/

  1. haha 2014 年 12 月 12 日

    作者作为一个前端开发,理解概念的能力确实弱了点,你所讲的 Oauth2.0 在原理上并不包含你所谓的绑定 QQ 帐号这一步,所以根本不是 Oauth2.0 有 XSRF,而是你们 QQ 添加的关联帐号功能有 XSRF,这是明显不同的概念。

  2. 爱国者 2013 年 8 月 4 日

    我发现国内的互联网公司拿 OAuth 进行用户身份认证(authetication)。OAuth 是为了解决用户对第三方应用进行授权的问题而提出的。

  3. 爱国者 2013 年 8 月 4 日

    Oauth 2.0 的 XSRF 的场景描述是不是有点问题? 当攻击者发起 OAuth 认证和绑定流程,使用自己的 QQ 号登陆,此时 QQ 授权服务器会返回对应于攻击者 QQ 号的授权码(authorization code)。因此即使受害者替攻击者执行了重定向网页的操作,第三方网站(aaa.com)执行后续的 OAuth 授权流程(用 authorization code 换取 access token),其 access token 只能用于获取攻击者自己的数据。

  4. perlt 2012 年 11 月 25 日

    关于 oauth1.0 ,
    这里用户去到登录授权后,会跳转回到授权回调的页面,这时候会重新带回新的 token 和 token_secret . 按道理说,攻击者用第一次调用 request_token 的接口是应该没办法进行获得 access__token 的步骤的??

    • TAT.Alloy

      AlloyTeam 2012 年 11 月 25 日

      嗯,这里没说清楚,关键在换取 request_token 的时候可以动态设置 oauth_callback。如果使用开发者设置的固定 url 则没有问题。
      文章已修改。

发表评论