从安全角度看Oauth2.0授权码模式

Posted 茉茉沐元

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从安全角度看Oauth2.0授权码模式相关的知识,希望对你有一定的参考价值。

1、redirect_uri


授权服务端必须验证client_id注册的应用与redirect_url是对应的,否则redirect_url会被伪造成第三方欺诈域名,直接导致服务器返回的code泄露。

举个例子:

https://wx.qq.com/code?

redirect_uri=https://mollytest.com&

client_id=11111&

response_type=code&

scope=userinfo

    因此OAuth2.0 认证服务器对redirect_uri 的域名限制与检查是一定要做的。

    <1>向授权方注册应用时,认证服务器端需要对redirect_uri进行检查禁止特殊字符输入,可以杜绝XSS攻击。

    <2>认证请求发送到认证服务器时,服务器端需要对redirect_uri进行全匹配,不做模糊匹配。


2、client_secret


    应用注册成功后,授权方服务将以client_id和client_secret的形式为应用发布客户端凭证,标识应用程序。

    ●Client_id是公开透明的字符串,存储在第三方应用客户端,用于构建呈现给用户的授权 url 。

    ●Client_secret用于验证应用身份,存储在第三方应用服务端,在客户端和服务之间保持私有性。

    如果 client_id 是为了告诉身份认证服务器,『我是 molly.com』,那么 client_secret 则是为了告诉身份认证服务器,『我真的是 molly.com!』。


3、code


    OAuth 2.0 当初设计的一个目标之一是,让不支持 HTTPS 的网站也能安全使用。既然提到了 HTTPS,必然跟中间人攻击有关系。继续往下说之前,我们再确认一下 OAuth 认证的要满足的条件:

    <1>要获取 access_token,必须先让用户在身份认证服务器上完成账户密码的输入(或已在登录时确认授权),因为不能把账号密码暴露给第三方应用。

    <2>access_token 必然要悄悄给第三方应用,因为不能被攻击者看到。

    我们先假设 OAuth 不需要整什么 code,就直接获取 access_token:

    <1>用户浏览器访问 molly.com,molly.com 服务器发现用户处于未登录状态,返回 302,让浏览器跳转到授权服务器 OAuth 服务获取 access_token,https://wx.qq.com/token?

client_id=xxx&

redirect_uri=http://molly.com&

scope=...

    <3>用户浏览器访问带 access_token 的链接,完成整个登录。

    此流程没大毛病,就是最后一步,如果 molly.com 不是 HTTPS 的网站,那么 access token 就等于暴露在浏览器和 chrisyue.com 服务器之间的线路中了。

    可能也有人会问,那多一步获取 code 有什么用呢?

    如果molly.com 不支持 HTTPS,code 不也是会被暴露吗?攻击者通过嗅探的方式截获到请求中传输的code,基于此进一步获取 access _token来登录受害人的账号。

    针对这个问题,OAuth2.0 协议其实对此是有处理方式的:

    <1>首先,授权服务端生成的临时code必须是一次有效,第三方应用使用一次后立即失效并且有效期很短,一般推荐30s。

    也就是说,攻击者最多让正常用户有点困扰,可能会出现登录意外失败,或者明明看起来登录成功但还是获取不到用户信息的情况(access_token 已经失效),但攻击者依旧拿不到数据。


再说回 secret。


    假设code 直接被发送到攻击者的服务器上,code 可是不会像上面说的那样会被执行两次,假如获取 access_token 不需要 access_secret,攻击者直接就拿 code 换 access_token 了。

    说到此 access_secret 的意义也不用多说了。因为access_secret 就是用来告诉 OAuth 服务器,『我真的是 xxx 网站不是假装的』,它其实就是第三方网站与 OAuth 服务网站之间的信物。此信物是一定一定不能被第三者知道的。如果知道了一定要第一时间重新生成。


4、State


    state 参数是为了保证申请 code 的设备和使用 code 的设备的一致而存在的。

    与 CSRF 攻击类似,如果 state 参数为空,作为攻击者,

    <1>先打开有道云官网,专门用于攻击他人的账号;

    <2>然后走正常流程,使用QQ账号授权登录;

    <3>授权成功之后,qq返回 code 回跳到 youdao.com,这个时候,攻击者拦截自己的请求让他不再往下进行,而直接将带 code 的链接发给受害者,并欺骗受害者点击;

    <4>受害人点击链接之后,继续攻击者账号的登录流程,不知不觉登录了攻击者的账号;

    <5>受害者如果这个时候没察觉此账号不是他本人的,在有道云笔记上传了一些隐私数据等,攻击者后面就能通过自己的账号看到。

    而 state 参数如果利用起来,当作 CSRF Token,就能避免此事的发生:

    <1>攻击者依旧获取 code 并打算骗受害者点击。

    <2>受害者点击链接,但因为有道云服务器分配给受害者的 state 值和链接里面的(分配给攻击者的)state 值不一样,有道云服务器直接返回验证 state 失败。

    state 或者说 CSRF Token 这种跟设备绑定的随机字符串,只要稍微复杂一点,攻击者根本就不可能猜得出来,而设置一个让攻击者猜不到的,跟设备或者说浏览器绑定的 state (CSRF token 同理) 值,就是解决 CSRF 攻击的关键。


5、Access_Token泄露


    由于Access_Token是通过http协议从服务器端传输给客户端,为了防止旁路监听泄露Access_Token,服务器必须提供https来保证传输通道的安全性(TSL的要求);

    第三方应用获取Access_Token,应该在第三方应用服务端与授权服务端交互获取Access_Token,原则是不允许Access_Token传给前端直接使用(但是现在很多系统使用不规范,会把Access_token作为自己应用的会话标识传到前端);

    需要保证Access_Token信息的不可猜测行,以防止被猜测得到。


6、令牌有效性漏洞


    Refresh_token存储在第三方应用服务端,维持refresh_token和第三方应用的绑定,刷新失效机制的设计不允许长期有效的access_token存在。


以上是关于从安全角度看Oauth2.0授权码模式的主要内容,如果未能解决你的问题,请参考以下文章

OAuth2.0 - 自定义模式授权 - 短信验证码登录

OAuth2.0系列之授权码模式实践教程

从0开始设计Oauth2.0 - 授权码模式

学习充电OAuth2.0安全设计之Authorization Code

oAuth2.0

#yyds干货盘点# OAuth2.0授权码模式实战