• Oauth2.0安全问题浅谈


    大家如果对Oauth还不是很了解可以先看下这篇文章https://www.cnblogs.com/maoxiaolv/p/5838680.html

    我这篇博客主要是总结一下安全测试过程中遇到Oauth2.0有哪些可能存在的漏洞,以及如何去测试。

    Oauth2.0协议流程

    (A)用户打开客户端以后,客户端要求用户给予授权。(比如说你登陆淘宝,但是不想注册淘宝账户,于是淘宝说你可以用QQ登陆哟,于是说好,这个时候淘宝将你引导至QQ的认证服务器)

    (B)用户同意给予客户端授权。(这个时候你在手机上弹出是否授权,你点击是,这个时候会返回一个授权码给淘宝,为什么是返回给淘宝呢?因为第一步中发送的认证服务器中会带有一个重定向url,是淘宝自己的)

    (C)客户端使用上一步获得的授权,向认证服务器申请令牌。(淘宝拿着这个授权码再去找认证服务器)

    (D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。(淘宝取人授权码无误后,发放accesstoken令牌)

    (E)客户端使用令牌,向资源服务器申请获取资源。(淘宝拿着令牌就可以访问QQ资源服务器)

    (F)资源服务器确认令牌无误,同意向客户端开放资源。(QQ资源服务器对比令牌无误后开放资源)

     

    上面有些细节没讲(例如url一般是怎样的),但不影响我们的测试。

    这里还要科普两个知识点:

    1.并不是什么网站都可以想QQ要授权的,比如说淘宝想和QQ搞这Oauth,必须先在QQ(服务提供商)那里进行注册,淘宝需要提供以下三个东西

      1)应用程序名称

      2)应用程序网站

      3)回调URL

      注册完成后,QQ会给淘宝两个东西

      1)Client ID (用于在构建上面B步骤中的请求url,这样QQ才知道是什么网站在找我要授权吧)

      2)Client Secret(也是淘宝要给QQ的东西,Client ID谁都知道可以伪造,这东西只有QQ和淘宝知道,至于是怎么给的还不知道)

    2.上面的C、D两个步骤属于授权过程,Oauth2.0提供了四种授权模式

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

      

     Oauth2.0协议本身没有什么问题,只是开发人员在实现授权过程中没有严格安装协议规定来,可能会导致一些常见的问题

     其中主要是前三种可能存在问题,先以授权码授权模式为例将下流程吧:

     

     

    授权码模式:

    A)用户访问客户端,客户端将用户引导向认证服务器。

    (B)用户选择是否给予客户端授权。

    (C)如用户给予授权,认证服务器将用户引导向客户端指定的redirection uri,同时加上授权码code。

    (D)客户端收到code后,通过后台的服务器向认证服务器发送code和redirection uri。

    (E)认证服务器验证code和redirection uri,确认无误后,响应客户端访问令牌(access token)和刷新令牌(refresh token)。

    请求示例

    A)步骤:客户端申请认证的URI(淘宝请求QQ)  

    https://www.example.com/v1/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read&state=xxx

     参数说明:

      response_type:授权类型,必选项,此处的值固定为"code"
      client_id:客户端的ID,必选项
      redirect_uri:重定向URI,必选项
      scope:申请的权限范围,可选项
      state:任意值,认证服务器会原样返回,用于抵制CSRF(跨站请求伪造)攻击。

    (C)步骤:服务器回应客户端的URI(用户点击授权后,QQ引导用户访问A步骤中指定的重定向url,并带着授权码和state)

    https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xxx

     参数说明:

      code:授权码,必选项。授权码有效期通常设为10分钟,一次性使用。该码与客户端ID、重定向URI以及用户,是一一对应关系。
      state:原样返回客户端传的该参数的值。

    (D)步骤:客户端向认证服务器申请令牌(淘宝带着接收到C步骤中的请求后,用授权码发送下面的请求去找QQ认证服务器要token)

    https://www.example.com/v1/oauth/token?client_id=CLIENT_ID&grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=CALLBACK_URL

    参数说明:

      client_id:表示客户端ID,必选项。
      grant_type:表示使用的授权模式,必选项,此处的值固定为"authorization_code"。
      code:表示上一步获得的授权码,必选项。
      redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。

    注意:协议里没有提及client_secret参数,建议可以使用此参数进行客户端的二次验证。

    (E)步骤:响应(D)步骤的数据

    复制代码
        {
           "access_token":"2YotnFZFEjr1zCsicMWpAA",
           "token_type":"example",
           "expires_in":3600,
           "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
           "example_parameter":"example_value"
         }
    复制代码

     参数说明:

      access_token:访问令牌,必选项。
      token_type:令牌类型,该值大小写不敏感,必选项。
      expires_in:过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
      refresh_token:更新令牌,用来获取下一次的访问令牌,可选项。
      scope:权限范围,如果与客户端申请的范围一致,此项可省略。

    使用场景

      • 授权码模式是最常见的一种授权模式,在oauth2.0内是最安全和最完善的。
      • 适用于所有有Server端的应用,如Web站点、有Server端的手机客户端。 
      • 可以得到较长期限授权。

    授权码授权模式常出现的安全问题是A步骤中,由于开发者没有严格按照协议来,请求中没有带上state,可能造成账户劫持的问题。正常情况下,淘宝先生成一个state并放在session中,然后再A步骤中的请求中带上state,QQ返回url带有授权码和state的链接给淘宝,淘宝这个时候需要在后台对比这个state是否和session中的一样,用来防止csrf攻击(这里将的有点啰嗦,实际上就是csrf嘛)。如果开发者在开发中没有使用state,我们也应该怎样测试呢?

    1.确认A步骤中是否带有state,如果没有该参数则存在漏洞

    2.准备AB两个账号,A是攻击者,B是受害者,两个都登陆的情况下,当然是不同的浏览器下喽(这里有个场景限制,就是绑定账户的地方才有,比如说我有各淘宝账户,但是要记住账号密码登陆很麻烦,我将他绑定到QQ,以后就可以直接用QQ登陆啦)

    3.A点击绑定QQ,然后用打开burp抓包,点击授权,一步一步forward,知道遇到请求中带有授权码的请求,复制该请求后drop掉,因为code一般都是一次性的

    4.拿去B账户的浏览器中打开(实际攻击中就是csrf嘛),会发现B账户绑定了A账户的QQ,以后A就可以用自己的QQ登陆B的淘宝了。

    隐身授权模式:

    A)客户端将用户引导向认证服务器。

    (B)用户决定是否给于客户端授权。

    (C)假设用户给予授权,认证服务器将用户导向客户端指定的”重定向URI",并在URI的Hash部分包含了访问令牌。

    (D)浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值。

    (E)资源服务器返回一个网页,其中包含的代码可以获取Hash值中的令牌。

    (F)浏览器执行上一步获得的脚本,提取出令牌。

    (G)浏览器将令牌发给客户端。

    请求示例

    (A)步骤:客户端发出请求

    https://www.QQ.com/authorize?response_type=token&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read&state=xxx

     参数说明 

      response_type:授权类型,此处的值固定为"token",必选项。
      client_id:客户端的ID,必选项。
      redirect_uri:重定向的URI,必选项。
      scope:权限范围,可选项。
      state: 任意值,认证服务器会原样返回,用于抵制CSRF(跨站请求伪造)攻击。

    (C)步骤:认证服务器响应客户端的请求url

    https://www.example.com/callback#access_token =ACCESS_TOKEN&state=xyz&token_type=example&expires_in=3600&state=xxx

     参数说明

      access_token:访问令牌,必选项。
      token_type:令牌类型,该值大小写不敏感,必选项。
      expires_in:过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
      scope:权限范围,如果与客户端申请的范围一致,此项可省略。
      state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。

    使用场景

      • 适用于所有无Server端配合的应用
      • 如手机/桌面客户端程序、浏览器插件。
      • 基于JavaScript等脚本客户端脚本语言实现的应用。

     

    这里主要讲下隐式授权和授权码授权的区别:

    两者主要是应用场景不同,授权码授权模式中淘宝是有自己的server端的,也就是说淘宝有自己的账户,只是想和QQ绑定而已。而隐式授权模式适用于比如说QQ自己的其他服务,比如英雄杀这种网页游戏,假设它自己有没有单独的server端,那么就可以使用隐式授权模式找QQ的其他服务要授权(这里有点说不清楚哈,大家意会,其实也不一定是QQ自己的其他服务,比如说我自己开了各三国杀的网站游戏,我不想要自己的服务器端,因为用户可能不想麻烦再注册账户,那么我用隐式授权模式实现QQ的开发的Oauth服务,这样用户就可以直接用QQ的账户登陆啦)

    说完大家就可以发现一个问题就是,隐式授权模式可能就不存在账户劫持的问题了,因为我(三国杀)都没有账户你怎么劫持呢?但是这里有个其他的问题:

    这是上面A步骤和C步骤发送的两个请求

    A   https://www.QQ.com/authorize?response_type=token&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read&state=xxx
    C   https://www.example.com/callback#access_token =ACCESS_TOKEN&state=xyz&token_type=example&expires_in=3600&state=xxx

    C步骤中的请求链接实际上来源A请求中的redirect_uri参数(用于指定重定向的链接),最为关键的地方是C请求中带有access_token,那么实际场景就是当state参数不存在的时候又可以进行csrf攻击了,伪造redirect_uri就好了,但正常情况下
    QQ至少会对redirect_uri的域名做校验吧,所以不能随便重定向,需要找到受信任的网站下的xss漏洞,然后重定向获取劫持access_token即可
    可以发现隐式授权如果存在问题一般是指服务提供商没有做好redirect_uri的校验,同时呢开发人员也没有加上state参数。


    密码模式授权:这个没什么好说的,就是需要用户输入QQ的账号密码。判断是否存在漏洞就是看下有没有爆破漏洞



    最后我还想说下sso(单点登陆的问题),sso和Oauth还是有区别的,sso主要是指比如我说登陆企业的OA后,我在OA里面再登陆企业邮箱啊、jira啊、wiki啊等等都不用再输入账号密码了,这就是单点登陆。
    sso存在的问题主要是盗取access_token后登陆他人账户,原因主要没有对redirect_uri做校验:
    场景一:和上面Oauth隐身授权模式的攻击手法一样,厂商只对域名做了校验,我们找到白名单中的域名下的xss漏洞进行利用就好了
    场景二:厂商没有做任何校验,这里和Oauth有些区别,sso不同的公司实现其他可能都有些不同,根据开发者的安全意识而异,所以可能对redirect_uri没有任何校验,这样利用起来就方便很多了,可以直接跳转到www.evil.com,同时这里还可以尝试javascript:alert(1)进行xss



    不能在写了,早上来就写这个,工作还没干呢


    ------------------------------------2020.6.3---------
    记录一下 去年发现fofa的OAuth 2.0的实现也有url跳转拿到code的问题,但是使用这个code依然实现不了账户劫持,思考了很久今天看了公司的OAuth 2.0文档后终于知道原因了

    因为这里第一次AS返回的code并不是access token 而是authorization code,浏览器拿到authorization code后,带着code state等参数请求client 客户端,由客户端通过authorization code去请求
    AS服务器交换access token (这里会携带client id和client secret去请求),这样拿到access token的过程是用户无感且不可控的(因为拿不到client secret),所以这里我拿到了authorization code
    也没办法获取access token




  • 相关阅读:
    poj----1330Nearest Common Ancestors(简单LCA)
    Tarjan--LCA算法的个人理解即模板
    hdu----(4545)魔法串(LCS)
    hdu---(1325)Is It A Tree?(并查集)
    hdu----(1599)最大子矩阵(几何/dp)
    hdu---(1054)Strategic Game(最小覆盖边)
    整理的一些模版LCS(连续和非连续)
    hdu---(4310)Hero(贪心算法)
    hdu----(4308)Saving Princess claire_(搜索)
    hdu------(4302)Holedox Eating(树状数组+二分)
  • 原文地址:https://www.cnblogs.com/jinqi520/p/10075471.html
Copyright © 2020-2023  润新知