Oauth认证
Lwwww Lv3

前言

一开始六月初学了一次Oauth,然后没学明白,什么什么code session的讲的好乱 看了几个文章其实很清楚 但是他们的字拼凑在一起就特别难以理解 包括后来看的burp靶场里面有一个Oauth的讲解,也是捋不清楚一直到昨天网上听北山团队的陈广师傅讲了一遍前端Oauth,才缓慢反应过来。

OAuth是一个在不提供用户名和密码的情况下,授权第三方应用访问web资源的安全协议 OAuth本身而言是一套很严谨的结构。

先把我认为的好文章分享一下放到这里

阮一峰的理解Oauth

OAuth2.0入门(一)—— 基本概念详解和图文并茂讲解四种授权类型

Burpsuite靶场之OAuth2.0漏洞及利用初探

一说起来Oauth可能不熟悉很陌生那么直接上截图就认识了

image

image

现在就应该很熟悉了 随处可见 的oauth 那么再来理解一下定义就很清晰了

1
OAuth 是一种常用的授权框架,它使网站和 Web 应用程序能够请求对另一个应用程序上的用户帐户进行有限访问。

简单介绍 Oauth2.0 原理

有两家互联网企业 A 和 B,其中 B 是一家提供相片云存储的公司。用户可以把相片上传到 B 网站上长期保存,然后可以在不同的设备上查看。某一天,A 和 B 谈成了一项合作:希望用户在使用 A 网站时,也可以观看他在 B 的相片。这个技术上要怎么实现呢?

  选项一:由 B 提供一个接口:

  GET /photos?account=

  参数:

    account : B 账号

  返回:

    指定账号下的所有相片

  有了这个接口,A 网站只需在界面上显示一个输入框,让用户输入他的 B 账号,然后调用这个接口来获取相片就可以了。

  这样可行吗?

回答当然是

NO!为啥?

  因为实现并开放这样一个接口,相当于直接把 B 公司的相片资源全部暴露在互联网中,虽然并没有公开,但是对于有点安全意识的技术人员来说,要发现这个接口简直轻而易举。这样的话,B 的用户就没有任何隐私了。

  那怎么办呢?这样吧,为了保证不能随便获取别人的相片,我们把接口改成这样:

  GET /photos?account=&pwd=

  除了要求用户输入账号,还要输入密码。只有当账号密码验证通过,才返回该账号下的所有相片。这样,即使黑客发现了这个接口,他不知道用户的密码,所以没办法窃取用户的相片了。这样 OK 了吧?

  答案还是 NO!绝不可以这么做!

  为什么?这里涉及到一个信任问题。如果这样实现,那么,用户必须在 A 的网站里输入他在 B 的账号和密码。如果你是一个隐私意识很强的人,你很可能会问:“凭什么我要把 B 的账号密码告诉 A ?”这里,从用户的角度就已经感受到一种不安全感,凭什么让我信任你 A,你保证不拿我的 B 账号密码去干坏事?而更深一层次,站在 B 的角度来考虑的话,也是一样的问题:我凭什么绝对信任 A?如果 A 在接收到用户的输入之后,马上就把请求发到我们这里来,那是 ok 的。但是万一 A 在这个过程偷偷把账号密码存起来了呢?那随着时间的推移,A 就慢慢地搜集到一大批 B 的账号密码!这对 B 来讲,是不能接受的!

  那怎么办呢?

  我们分析一下这个问题产生的原因,主要是在于 A、B、用户 三方的交互模型有问题。请看:

image

在这个场景下,用户需要访问他在 B 的相片资源,但是他不能直接和 B 打交道,而是必须通过 A。在这个前提下去考虑问题,无论如何无法想出一个既能实现功能,又能让用户和 B 都感到放心的实现方案。

  Oauth2.0 就是为了解决这个问题而提出来的交互模型。它告诉人们,在这种场景下,三方要怎么打交道,才能做到安全、合理。

  具体来说,Oauth2.0 的交互模型的核心是这个样子的:

image

 解释一下几个术语。

  资源服务器。即资源的存放地点,或者说资源的访问入口。在例子中,资源服务器即 get photos 接口所部署的服务器。A 必须经由这里去访问资源。

  鉴权服务器。这是一个对用户的身份进行认证、并对 A 进行授权的地方。这也是 Oauth2.0 的关键节点。通常情况下,鉴权服务器也是属于 B 公司的。

  好,接下来看看整个交互过程是怎样的。

  首先,同样是用户在访问 A 的网站,然后,A 需要访问 B 用户的相片。这个时候,A 并不是展示一个输入框给用户,而是打开一个页面。这个页面就是 B 部署在鉴权服务器上面的一个鉴权页面,通常情况下,它长得类似下面这个样子:image

上面这个是腾讯给有道云笔记进行授权的页面。这里,腾讯就是 B,有道云笔记就是 A。(这页面是不是很熟悉?在哪见过?有兴趣了解一下账号接出的原理,其实就是Oauth2.0。)

  这个页面有两个要素:

  1,有认证机制。在腾讯这个例子中,你需要输入QQ账号密码,证明你是一个合法的QQ用户

  2,展示了授权信息。看页面右方“有道云笔记将获得以下权限”部分。这是在告诉用户,如果你授权给 A,那么,A 将获得访问你这些资源的权限

  注意,这个页面是部署在 B 的鉴权服务器上,所有用户输入的账号密码是直接提交给 B,A 是没有任何机会拿到的。

  如果用户同意授权并且认证通过,那么,接下来鉴权服务器会通知 A,并给 A 发送一个访问令牌(access token,其实就是一段全局唯一的随机字符串)。有了这个访问令牌,A 就可以拿着它去找资源服务器要资源了。

  所以,获取相片的接口会是类似这个形式(实际当中不会把 access token 放在 query string 中,这里做了简化):

  GET /photos?accesstoken=

  资源服务器在接收到这个请求之后,会拿着 access token,再去找鉴权服务器,检查这个 access token 的合法性和权限,如果通过的话,才返回资源给 A。

  如此,即实现了功能,也保障了安全性。不过你可能会问,这个 access token 和账号密码的区别是什么呢?都是代表用户身份的,为什么 access token 就更安全?答案是:

  1,账号密码是一切,有了账号密码就几乎可以做任何事情(甚至改掉原密码)。而 access token 是有限制范围的。每个 access token 都有一个 scope,也就是允许执行哪些操作。

  2,access token 是有有效期的。如果 access token 被窃取,也不能一直用。

Authorization Code 授权原理和实现方法

Oauth2.0 定义了几种授权流程,其中最重要、也最基础的是 Authorization Code 授权。也就是授权码类型先看流程图:

授权码类型

image

1,用户访问 A 网站

  2,A 打开 B 的授权页面

  3,用户看到授权界面,输入账号密码进行授权

  4,B 验证用户是合法的之后,生成一个 authorization code,然后通过 302 跳转的方式,把这个 code 发送给 A

  5,A 用这个 code 调用 B 的 api,获得 access token

  6,A 用 access token 访问资源

  问题来了,authorization code 是什么?

  - code 一个一次性的临时凭证,可以用它来兑换 access token

  - code 是由鉴权服务器生成的一个随机且唯一的字符串

  - 鉴权服务器会记录下 code 的生成时间、将要兑换给谁(例子里是 A)、授权的用户是谁

  - 在第 5 步,鉴权服务器会验证 A 的身份,并且检查 code 的有效期。通过的话就会生成 access token

  - code 是一次性的,在第 5 步成功换取 access token 之后就会作废

  - code 的有效期非常短,可能不会超过 1 分钟。A 在第 4 步获取到 code 之后,要立刻走第 5 步

当然这些情况并不是绝对的这也是为什么把他们单拿出来强调

  为什么不在第 4 步直接把 access token 发送给 A,而要通过看似多余的 code 再转换一下,搞这么复杂呢?这个问题的答案非常重要,是整个授权流程的关键所在。

  如果在第 4 步直接把 access token 发送给 A,会有什么问题呢?

  问题就是,第 4 步是一个 302 跳转,如果在第 4 步传递 access token,会导致 access token 暴露在 url 中,这是非常不安全的方式,因为 url 很容易捕捉到。

  所以我们不能在第 4 步直接传递 access token。那换成一个 code,再用 code 去换,就更安全了吗?你可以能会问,code 同样会泄漏,那攻击者拿到 code,也可以用 code 去换 access token,有什么区别呢?

  区别在于,攻击者拿到 code 是不能拿去换 access token 的,两个原因:

  1,上面说了,换取 access token 的时候,鉴权服务器会验证 A 的身份。具体怎么验证,在后面说明。

  2,code 的有效期极短,留给攻击者的时间极短

  另外,即便攻击者成功突破了上面两个限制,拿到了 access token,鉴权服务器也能很快发现。这是因为,攻击者必须抢在 A 之前去兑换 access token。那么,等到 A 走第 5 步的时候,鉴权服务器就会发现,这个 code 已经被用过了。此时这就是一个攻击已经发生的信号:有两个不同的服务器,尝试用同一个 code 来兑换 access token,正常情况下是不应该发生的。此时鉴权服务器可以立刻采取措施。例如,可以把刚才兑换出去的 access token 作废。所以,搞出来一个 code,确实会安全很多。

  那么,怎么验证 A 的身份呢?

  所有的 A,应该说都是 B 的合作方。那么在开始合作之前,一定需要做一些前期的准备。具体来说,B 通常会提供一个申请网站,A 通过这个网站填写一些信息,提交合作申请。B 的工作人员会审核,通过之后,系统会给 A 自动分配一个 client_id 和一个 client_secret。client_id 就是一个唯一 id,client_secret 是一个密钥。A 需要把 client_secret 妥善保管在服务器上,不能泄露。在用 code 兑换 access token 的时候,需要用这个 client_secret 对请求生成 MAC(消息验证码)。鉴权服务器就是依靠这个 MAC 来验证 A 的身份的。

  这里需要用到密码学的知识,本文就不展开解释了,有兴趣请看 什么是消息验证码MAC 。总之,攻击者因为没有这个密钥,无法对请求做出 MAC,因此就算窃取到 code,也不能用 code 来兑换 access token。

  根据上面的梳理,可以知道,要实现一套 Authorization Code 授权流程,需要做两个 endpoint:

  

  1,Auth Endpoint: GET /oauth2/auth  这就是第 2 步的授权页面地址

  参数:

    client_id 发起授权的合作方的 client_id。必填

    redirect_uri 回调地址,也就是第 4 步 302 跳转的地址,用于接收 code。这个参数是可选的。因为在前期发起合作申请的时候,A 是需要提前将这个地址注册给 B 的。如果没有传,则使用注册的默认值

    scope 授权范围。这个也是可选的。B 可以把资源进行划分,分成多个 scope。A 发起授权的时候,可以指明要哪些 scope 的访问权限

    state 一个由 A 生成的,随机且唯一的字符串。这个是用来防 CSRF 攻击的

image

1
2
3
4
当用户访问资源时,比如在网易云音乐中使用第三方登录功能,例如QQ登录,那么这里的资源就是用户的QQ昵称和头像等信息。此时第三方应用(网易云音乐)将发送请求到授权服务器(QQ)去获取授权,此时授权服务器(QQ)将返回一个界面给用户,用户需要登录到QQ,并同意授权网易云音乐获得某些信息(资源)。当用户同意授权后,授权服务器将返回一个授权码(Authorization Code)
给第三方应用,此时第三方应用在通过client_id、client_secret(这是需要第三方应用在授权服务器去申请的)和授权码去获得Access Token和Refresh Token,此时授权码将失效。然后就是第三方应用通过Access Token去资源服务器请求资源了,资源服务器校验Access Token成功后将返回资源给第三方应用。
这个是我点击qq登录后推送的页面
graph.qq.com/oauth2.0/show?which=Login&display=pc&client_id=100312028&response_type=code&redirect_uri=https%3A%2F%2Fpassport.baidu.com%2Fphoenix%2Faccount%2Fafterauth%3Fmkey%3D95a67454940271d50cfcde5e933cbe5921cd3c0297e652c6dc%26tpl%3Dmn&state=1750154092&display=page&scope=get_user_info%2Cadd_share%2Cget_other_info%2Cget_fanslist%2Cget_idollist%2Cadd_idol%2Cget_simple_userinfo&traceid=
1
graph.qq.com/oauth2.0/show?which=Login&display=pc&**client_id=100312028**&response_type=code&redirect_uri=https://passport.baidu.com/phoenix/account/afterauth?mkey=95a67454940271d50cfcde5e933cbe5921cd3c0297e652c6dc&tpl=mn&state=1750154092&display=page&scope=get_user_info,add_share,get_other_info,get_fanslist,get_idollist,add_idol,get_simple_userinfo&traceid=

client_id对应出来了第一步,但是由于我们还没有登录到qq的oauth认证的板块也就是看到的graph.qq.com的域名 所以不能进行下一步–确认授权

image

image

1
POST /speed?id=RiaWqsnT3403yXTgVY&uin=5e637f0000012299-097977a4fd7a8afa-9020&version=9fce2a54&aid=f61ac0fc-29e6-4a54-ba88-1410ed52a180&env=production&platform=3&netType=100&vp=407 * 331&sr=1920 * 1080&sessionId=session-1750155370383&from=https://xui.ptlogin2.qq.com/cgi-bin/xlogin?appid=716027609&daid=383&style=33&login_text=登录&hide_title_bar=1&hide_border=1&target=self&s_url=https://graph.qq.com/oauth2.0/login_jump&pt_3rd_aid=100312028&pt_feedback_link=https://support.qq.com/products/77942?customInfo=www.baidu.com.appid100312028&theme=2&verify_theme=&referer=https://graph.qq.com/

image

然后回包是这样的

1
response_type=code&client_id=100312028&redirect_uri=https://passport.baidu.com/phoenix/account/afterauth?mkey=188101cf26a4c3a6ce7bcd20322fe5c6e1506adeb783209b76&tpl=mn&scope=get_user_info,add_share,get_other_info,get_fanslist,get_idollist,add_idol,get_simple_userinfo&state=1750300730&switch=&from_ptlogin=1&src=1&update_auth=1&openapi=1010&g_tk=1573676930&auth_time=1750300769539&ui=A78DC9BA-5CF3-4B9D-A2A2-6A998F4002C4

image

 给亮汪汪买点狗粮吧⋆⋅☆(✪Ω✪)☆⋅⋆
Powered by Hexo & Theme Keep
Total words 28k Unique Visitor Page View