话说前段时间 OAuth2.0 授权被人找出了个漏洞,各个开放平台都有影响,导致一阵恐慌。虽然后来发现其实是夸大其后果了,但也暴露出我们对这个经常用的协议仍一知半解的现状。所以花了点时间,整理了 OAuth1.0 和 2.0 的授权流程、以及其中的隐患和修复方案,供各位同学了解。由于本人也是临阵磨刀,难免疏漏,欢迎指点。
一、OAuth 1.0
a)OAuth1.0的授权流程为
[caption id="attachment_1461" align="alignnone" width="600"] OAuth1.0授权流程(配图取自http://dev.t.qq.com/)
more其特点是请求request_token是需要传入app key和app secert, 而app secert是不能公开的, 因此只适合于服务器端授权。同时授权时的交互步骤比较多, 不够简便。
二、OAuth 2.0
a) OAuth2.0有两种授权方式
- Authorization code grant (Server Side),适合于有server端的应用授权
- Implicit grant(Client Side),适合于通过客户端访问的应用授权
b) Server Side的流程为
[caption id="attachment_1463" align="alignnone" width="554"] 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的流程为
[caption id="attachment_1464" align="alignnone" width="593"] 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
- 攻击者访问可靠的第三方站点(aaa.com), 在该网站发起OAuth认证流程, 保存包含request_token的授权URL1, 但不定向到该URL1所指的页面
- 把URL1中的oauth_callback参数改掉,换成攻击者自己的页面hack1,组成新的URL2,把该URL2发给受害者, 诱骗受害者点击
- 受害者点击URL2打开授权页, 发现是可靠的站点, 而不会发现有潜在的隐患, 因此会进行授权
- 受害者授权之后, 会回调到攻击者自己的页面hack1,攻击者就可以从这个页面获取到已授权的request_token和verifier,用这两个参数就能直接走到授权的第5步, 用request_token即可换取到access_token, 之后就可以使用access_token 访问受害者的数据(个人资料、私密文章之类的)了,如果这个网站(aaa.com)改密码的时候不用输入原密码,那么受害者的密码也会被改掉。
b) OAuth 2.0 (Server Side)
- 攻击者访问可靠的第三方站点(aaa.com), 且该网站提供了绑定帐号功能, 在该网站使用攻击者自己的帐号account1(aaa.com上的账号)发起OAuth认证和绑定流程(例如绑定qq账号), 之后用他自己的qq号qq1登录,然后保存包含code的重定向URL1, 但不定向到该URL1所指的页面
- 构造一个自动发起绑定请求的页面, 如创建一个img,src="url1"。 然后把该页面URL2发给受害者, 诱骗受害者点击
- 受害者点击URL2时, 如果恰好在 aaa.com (account2)登录了, 浏览器存有aaa.com的登录态, 这时就自动把受害者在aaa.com的帐号绑定到qq1上了
- 攻击者现在只要用qq1登录aaa.com, 就能访问到 受害者的数据(个人资料、私密文章之类的,甚至也能改密码)。
c) OAuth 2.0(Client Side)
Client Side的授权流程本身没有该问题, 不过由于Client Side是设计来给没有server的移动应用使用的, 其获取的access_token是保存在客户端的, 因此这里有泄漏的风险。
四、XSRF修复
- 可以要求OAuth1.0 的方式升级到 2.0, 由于1.0跟2.0的协议相差较大, 因此会有不少迁移特别是调试的工作;若保持使用OAuth1.0,则可以限制oauth_callback为固定url,不允许动态设置。
- 而OAuth 2.0 (Server Side)的方式, 可以要求app server必须对state进行验证, 从受害者发起的绑定请求, 由于他是中途进入的, app server上并没有保存相应的state, 这时server可以拒绝掉这次绑定请求。
- OAuth 2.0(Client Side)并没有这个问题, 可以不用修复。 重点在如何安全的保存access_token上。
此文写的很好!!确实存在上面问题。v1, 新浪微博的callback,会在server端设置的,如果客户端传参不是同一个callback地址会报错的。