OAuth2.0原理与攻击面

OAuth2.0协议原理

OAuth 2.0 是目前最流行的授权机制,用来授权第三方应用,获取部分用户数据。

OAuth2.0是OAuth协议的下一版本,但不向后兼容OAuth 1.0。2012年10月,OAuth 2.0协议正式发布为RFC 6749 (Request For Comments 互联网标准文件,按编号排列)。

特点

  1. OAuth 的核心就是向第三方应用颁发令牌
  2. OAuth 2.0 规定了四种获得令牌的流程。你可以选择最适合自己的那一种,向第三方应用颁发令牌

应用
统一认证登陆、第三方账号绑定登陆

令牌与密码

令牌(token)与密码(password)的作用是一样的,都可以进入系统,但是有三点差异。

(1)令牌是短期的,到期会自动失效,用户自己无法修改。密码一般长期有效,用户不修改,就不会发生变化。

(2)令牌可以被数据所有者撤销,会立即失效。以上例而言,屋主可以随时取消快递员的令牌。密码一般不允许被他人撤销。

(3)令牌有权限范围(scope),比如只能进小区的二号门。对于网络服务来说,只读令牌就比读写令牌更安全。密码一般是完整权限。

上面这些设计,保证了令牌既可以让第三方应用获得权限,同时又随时可控,不会危及系统安全。这就是 OAuth 2.0 的优点。

注意,只要知道了令牌,就能进入系统。系统一般不会再次确认身份,所以令牌必须保密,泄漏令牌与泄漏密码的后果是一样的。 这也是为什么令牌的有效期,一般都设置得很短的原因。

OAuth的参与实体

至少有如下4个:

  • RO (resource owner): 资源所有者,即用户,对资源具有授权能力。
  • AS (authorization server):授权服务器,它认证RO的身份,为RO提供授权审批流程,并最终颁发授权令牌(Access Token)。
  • RS (resource server):资源服务器,它存储资源,并处理对资源的访问请求。AS与RS可以是同一个服务器。
  • Client: 第三方应用,它获得RO的授权后便可以去访问RO的资源。

OAuth2.0流程

OAuth2.0原理与攻击面

第二步授权中,OAuth2.0提供多种授权模式。
前提:第三方应用现在授权服务器上申请client_idclient_secret

重点来了

授权模式:

  • 授权码模式 (Authorization Code Grant)
  • 隐式授权/简化授权模式 (Implicit Grant)
  • RO凭证授权/密码模式 (Resource Owner Password Credentials Grant)
  • 客户端授权模式 (Client Credentials Grant)

授权码模式

这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。
OAuth2.0原理与攻击面

简化模式

适用于纯前端模式,所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。
OAuth2.0原理与攻击面
相比授权码模式,没有code

客户端模式

客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。
OAuth2.0原理与攻击面

密码模式

如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌
OAuth2.0原理与攻击面

令牌刷新

令牌的有效期到了,如果让用户重新走一遍上面的流程,再申请一个新的令牌,很可能体验不好,而且也没有必要。OAuth 2.0 允许用户自动更新令牌。

具体方法是,授权服务器颁发令牌的时候,一次性颁发两个令牌,一个用于获取数据,另一个用于获取新的令牌(refresh token 字段)。令牌到期前,客户端使用 refresh token 发一个请求,去更新令牌,不需要用户参与授权。

安全漏洞

OAuth2.0协议本身没有问题,出现安全问题的是协议在使用过程中的不规范,没有严格遵循协议的安全相关指导造成的。

本文总结的安全漏洞针对授权码模式和隐式授权模式

access_token未绑定用户

简化模式授权access_token暴露在前端且未进行严格检验。
举个栗子
A用户通过weibo登录hhh.com,验证weibo账号通过后跳回hhh.com并返回access_token
url:http://hhh.com/sina_login.php?redirect_url=http://hhh.com/#access_token=xxxxxxxxxxxxxx&remind_in=******&expires_in=******&uid=******
其中对认证用户身份的参数进行攻击:

  1. 替换uid,只要uid存在就可成功登录他人账号
  2. 替换access_token为B账号token,可登录B账号

OAuth 2.0在对待手机、平板之类应用的授权的问题上,一般都倾向于返回access token;然后由应用将access token上报给服务器,以进行应用自身的账号认证登录。这种场景的变化导致被篡改的难度大大降低,但许多手机开发者、乃至手机背后的服务器api开发者并没有意识到,结果错误选择了授权信息作为参数(比如单纯选择uid)、或者没有对授权信息(access token)进行来源验证,从而导致这类漏洞大爆发。

CSRF绑定劫持

授权码模式
前情提要:A用户在hhh.com拥有一个账号A,hacker希望用自己的weibo账号绑定A账号,从而登陆A账号进行恶意操作。

攻击流程:

  1. hacker在hhh.com注册一个账号B,点击绑定weibo,一路进行到返回code步骤redirect_url=http://hhh.com/weibo_login&code=******
  2. hacker保存此url,并将此url发给A用户
  3. A用户点击url后将code发给认证服务器,继续进行hacker未完成的操作
  4. A用户得到access_token,但是此token携带的是hacker的weibo账号信息
  5. 账号A成功绑定了hacker的weibo账号
  6. hacker可以使用自己的weibo账号登录hhh.com愉快地操作了~

防御
OAuth 2.0提供了state参数用于防御CSRF。其实就是csrf_token的一种形式,认证服务器在接收到的state参数按原样返回给redirect_uri,客户端收到该参数并验证与之前生成的值是否一致

redirect_url授权劫持

简化授权模式

简化授权模式场景的特点是授权验证时只需要client_idredirect_uri这两个参数作应用标识,返回的时候也就直接在url片段中返回access_token

若未严格限制,简化授权模式结合xss可拿到access_token

http://hhh.com/oauth/grant?client_id=cd271e3051444285b8a18f1211a095cd&redirect_uri=http://xss_url/&response_type=token

授权过程中修改redirect_url为一存在XSS的网站,当授权成功返回access_token时跳到xss网站,攻击者通过referer获得token

授权码模式

授权码模式access_token不返回前端,但是code返回,所以攻击者的目标是拿到code,跟前面拿token一个流程

防御

严格限制url跳转

参考:
深入理解OAuth2.0&基于OAuth2.0第三方登录之GitHub实践
OAuth2.0协议详解
猴子都能看懂的简易图解
OAuth2.0漏洞案例
https://www.freebuf.com/articles/web/110757.html
https://gh0st.cn/archives/2018-02-12/1