OAuth授权的XSRF漏洞及其修复
或说前段时间 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有两种授权方式
- Authorization code grant (Server Side),适合于有server端的应用授权
- 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
- 攻击者访问可靠的第三方站点(aaa.com), 在该网站发起OAuth认证流程, 保存包含request_token的授权URL, 但不定向到该URL所指的页面
- 把该URL发给受害者, 诱骗受害者点击
- 受害者点击URL打开授权页, 发现是可靠的站点, 而不会发现有潜在的隐患, 因此会进行授权
- 受害者授权之后, 攻击者就可以用上次保存的request_token, 直接走到授权的第5步, 用request_token即可换取到access_token, 之后就可以使用access_token 访问受害者的数据了。
b) OAuth 2.0 (Server Side)
- 攻击者访问可靠的第三方站点(aaa.com), 且该网站提供了绑定帐号功能, 在该网站使用攻击者自己的帐号account1 发起OAuth认证和绑定流程, 保存包含code的重定向URL1, 但不定向到该URL所指的页面
- 构造一个自动发起绑定请求的页面, 如创建一个img,src=”url1″。 然后把该页面URL2发给受害者, 诱骗受害者点击
- 受害者点击URL2时, 如果恰好在 aaa.com 登录了, 浏览器存有aaa.com的登录态, 这时就自动把受害者在aaa.com的帐号绑定到account1上了
- 攻击者现在只要用account1登录aaa.com, 就能访问到 受害者的数据。
c) OAuth 2.0(Client Side)
Client Side的授权流程本身没有该问题, 不过由于Client Side是设计来给没有server的移动应用使用的, 其获取的access_token是保存在客户端的, 因此这里有泄漏的风险。
四、XSRF修复
- 可以要求OAuth1.0 的方式升级到 2.0, 由于1.0跟2.0的协议相差较大, 因此会有不少迁移特别是调试的工作;
- 而OAuth 2.0 (Server Side)的方式, 可以要求app server必须对state进行验证, 从受害者发起的绑定请求, 由于他是中途进入的, app server上并没有保存相应的state, 这时server可以拒绝掉这次绑定请求。
- OAuth 2.0(Client Side)并没有这个问题, 可以不用修复。 重点在如何安全的保存access_token上。
[ comments ]