Translated ['', 'src/pentesting-cloud/azure-security/az-basic-informatio

This commit is contained in:
Translator
2026-02-05 12:37:55 +00:00
parent 0831f1ecda
commit e1fb7222dd

View File

@@ -1,100 +1,100 @@
# Az - Tokens & Public Applications
# Az - 令牌与公共应用程序
{{#include ../../../banners/hacktricks-training.md}}
## 基本信息
Entra ID 是微软基于云的身份访问管理 (IAM) 平台,作为 Microsoft 365 和 Azure Resource Manager 等服务的基础证和授权系统。Azure AD 实现了 OAuth 2.0 授权框架和 OpenID Connect (OIDC) 证协议,以管理对资源的访问。
Entra ID 是 Microsoft 的云端身份访问管理 (IAM) 平台,作为 Microsoft 365 和 Azure Resource Manager 等服务的基础身份验证和授权系统。Azure AD 实现了 OAuth 2.0 授权框架和 OpenID Connect (OIDC) 身份验证协议管理对资源的访问。
### OAuth
**OAuth 2.0 的关键参与者:**
1. **资源服务器 (RS)** 保护资源所有者拥有的资源。
2. **资源所有者 (RO)** 通常是拥有受保护资源的终用户。
3. **客户端应用程序 (CA)** 代表资源所有者请求访问资源的应用程序
4. **授权服务器 (AS)**验证和授权客户端应用程序后向其发放访问令牌
1. **Resource Server (RS)** 保护资源所有者拥有的资源。
2. **Resource Owner (RO)** 通常是拥有受保护资源的终用户。
3. **Client Application (CA)** 代表资源所有者请求访问资源的应用。
4. **Authorization Server (AS)**认证并授权客户端应用后向其颁发 access tokens
**范围和同意:**
**Scopes 与 同意:**
- **范围** 在资源服务器上定义的细粒度权限,指定访问级别。
- **同意** 资源所有者授予客户端应用程序访问特定范围资源的权限的过程。
- **Scopes** 在资源服务器上定义的细粒度权限,用于指定访问级别。
- **Consent** 资源所有者授予客户端应用以特定 scopes 访问资源的过程。
**Microsoft 365 集成:**
- Microsoft 365 用 Azure AD 进行 IAM并由多个“第一方”OAuth 应用程序组成。
- 这些应用程序深度集成,通常具有相互依赖的服务关系。
-简化用户体验并持功能,微软对这些第一方应用程序授予“隐含同意”或“预先同意”。
- **隐含同意:** 某些应用程序在没有明确用户或管理员批准的情况下**自动获得对特定范围的访问权限**。
- 这些预先同意的范围通常对用户和管理员都隐藏,使其在标准管理界面中不太可见
- Microsoft 365 使用 Azure AD 作为 IAM并由多个 “first-party” OAuth 应用组成。
- 这些应用深度集成,通常具有相互依赖的服务关系。
- 为简化用户体验并持功能,Microsoft 会对这些 first-party 应用授予“implied consent”或“pre-consent”。
- **Implied Consent** 某些应用会被自动**授予对特定 scopes 的访问权限,而无需明确用户或管理员批准**。
- 这些预先同意的 scopes 通常对用户和管理员都隐藏,使其在标准管理界面中不易被看到
**客户端应用程序类型:**
**客户端应用类型:**
1. **机密客户端**
- 拥有自己的凭据(例如密码或证书)。
- 可以**安全地授权服务器进行身份验证**。
2. **公共客户端**
- 没有唯一凭据。
- 不能安全地向授权服务器进行身份验证。
- **安全隐患** 攻击者可以在请求令牌时冒充公共客户端应用程序,因为授权服务器没有机制来验证应用程序的合法性。
1. **Confidential Clients**
- 拥有自己的凭据(例如密码或证书)。
- 可以**安全地授权服务器进行自身认证**。
2. **Public Clients**
- 没有唯一凭据。
- 无法向授权服务器进行安全认证。
- **安全含义** 当请求 tokens 时,攻击者可以冒充 public client 应用,因为授权服务器无法验证应用的合法性。
## 证令牌
## 身份验证令牌
OIDC 中使用**三种类型的令牌**
OIDC 中使用**三种令牌**
- [**访问令牌**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** 客户端将此令牌呈现给资源服务器以**访问资源**。它只能用于特定的用户、客户端和资源组合,并且**在到期之前无法被撤销** - 默认情况下为 1 小时。
- **ID 令牌**客户端从**授权服务器**接收**令牌**。它包含关用户的基本信息。它**绑定到特定的用户客户端组合**。
- **刷新令牌**:与访问令牌一起提供给客户端。用于**获取新的访问和 ID 令牌**。它绑定到特定的用户客户端组合并且可以被撤销。默认过期时间为**90 天**(对于不活动的刷新令牌)和**活动令牌没有过期**(可以从刷新令牌获取新的刷新令牌)。
- 刷新令牌应与**`aud`**、某些**范围**和**租户**相关联,并且只能为该 aud、范围(且不更多)和租户生成访问令牌。然而,这在**FOCI 应用程序令牌**中并非如此
- 刷新令牌是加密的,只有微软可以解密它。
- 获取新的刷新令牌不会撤销前的刷新令牌
- [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**** 客户端向资源服务器出示此 token 以**访问资源**。它只能用于特定的用户、客户端和资源组合,并且在过期之前**无法被撤销**——默认有效期为 1 小时。
- **ID Tokens** 客户端从授权服务器接收**token**。它包含关用户的基本信息。它**绑定到特定的用户客户端组合**。
- **Refresh Tokens** 与 access token 一起提供给客户端。用于**获取新的 access 和 ID tokens**。它绑定到特定的用户客户端组合并且可以被撤销。默认过期为**90 天**(对于不活跃的 refresh tokens并且**活动 token 默认不失效**(通过 refresh token 可以获取新的 refresh tokens)。
- 一个 refresh token 应该绑定到一个 **`aud`**、一些 **scopes** 和一个 **tenant**,并且它应只能为该 aud、这些 scopes且不能超出和该 tenant 生成 access tokens。然而,**FOCI applications tokens** 并不遵循该约束
- refresh token 是加密的,只有 Microsoft 能解密它。
- 获取新的 refresh token 并不会撤销前的 refresh token
> [!WARNING]
> **条件访问**的信息存储在**JWT**。因此,如果您从**允许的 IP 地址**请求**令牌**,该**IP**被**存储**在令牌中,然后可以从**不允许的 IP 访问资源**使用该令牌
> 有关 **conditional access** 的信息**存储**在 **JWT**。因此,如果你从一个**允许的 IP 地址**请求了该**token**,该**IP**被**存储**在 token 中,然后可以从一个**未被允许的 IP**使用该 token 来访问资源
### 访问令牌 "aud"
### Access Tokens "aud"
aud字段中指示的字段是用于执行登录的**资源服务器**(应用程序)。
"aud" 字段中指示的是用于执行登录的**resource server**应用)。
命令 `az account get-access-token --resource-type [...]` 支持以下类型,每种类型将在结果访问令牌中添加特定的aud
命令 `az account get-access-token --resource-type [...]` 支持以下类型,每种类型都会在生成的 access token 中添加特定的 "aud"
> [!CAUTION]
> 注意,以下仅是 `az account get-access-token` 支持的 API还有更多
> 注意,以下仅是 `az account get-access-token` 支持的部分 API并不止这些
<details>
<summary>aud 示例</summary>
- **aad-graph (Azure Active Directory Graph API)**:用于访问遗留的 Azure AD Graph API已弃用允许应用程序读取和写入 Azure Active Directory (Azure AD) 中的目录数据。
- **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 资源。这包括创建、更新和删除虚拟机、存储帐户等资源的操作
* **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这是一项服务,可在云中高效地启用大规模并行和高性能计算应用程序
- **batch (Azure Batch Services)**:用于访问 Azure Batch该服务支持在云中高效运行大规模并行和高性能计算应用。
- `https://batch.core.windows.net/`
* **data-lake (Azure Data Lake Storage)**:用于与 Azure Data Lake Storage Gen1 交互,这是一可扩展的数据存储分析服务。
* **data-lake (Azure Data Lake Storage)**:用于与 Azure Data Lake Storage Gen1 交互,这是一可扩展的数据存储分析服务。
- `https://datalake.azure.net/`
- **media (Azure Media Services)**:用于访问 Azure Media Services提供基于云的视频和音频内容处理和交付服务。
- **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、企业移动性安全服务等服务的数据和见解
* **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。
- **oss-rdbms (Azure Open Source Relational Databases)**:用于访问 Azure 开源关系数据库服务,如 MySQL、PostgreSQL 和 MariaDB。
- `https://ossrdbms-aad.database.windows.net`
</details>
### 访问令牌范围 "scp"
### Access Tokens Scopes "scp"
访问令牌的范围存储在访问令牌 JWT 的 scp 键中。这些范围定义了访问令牌可以访问的内容。
access token 的 scope 存储在 access token JWT 的 scp 键中。这些 scopes 定义了 access token 可以访问的内容。
如果 JWT 被允许联系特定 API但**没有范围**来执行请求操作,它**将无法使用该 JWT 执行该操作**。
如果一个 JWT 被允许联系某个特定 API但**没有执行请求操作的 scope**,那么该 JWT **将无法执行该操作**
### 获取刷新和访问令牌示例
### 获取 refresh & access token 示例
```python
# Code example from https://github.com/secureworks/family-of-client-ids-research
import msal
@@ -106,7 +106,7 @@ 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
"00b41c95-dab0-4487-9791-b9d2c32c80f2" # ID for Office 365 Management
)
device_flow = azure_cli_client.initiate_device_flow(
scopes=["https://graph.microsoft.com/.default"]
@@ -144,31 +144,32 @@ scopes=["https://graph.microsoft.com/.default"],
)
pprint(new_azure_cli_bearer_tokens_for_graph_api)
```
### 其他访问令牌字段
### Other access token fields
- **appid**: 用生成令牌的应用程序 ID
- **appidacr**: 应用程序身份验证上下文类引用指示客户端的身份验证方式,对于公共客户端,值为 0如果使用了客户端密钥则值为 1
- **acr**: 身份验证上下文类引用声明在最终用户身份验证未满足 ISO/IEC 29115 要求时为 "0"。
- **amr**: 身份验证方法指示令牌是如何被验证的。值为“pwd”表示使用了密码。
- **groups**: 指示主体是哪些组的成员
- **iss**: 发行者标识生成令牌的安全令牌服务 (STS)。例如 https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/uuid 是租户 ID
- **oid**: 主体的对象 ID
- **tid**: 租户 ID
- **iat, nbf, exp**: 签发时间(何时签发)、不早于(在此时间之前不能使用,通常与 iat 相同)过期时间。
- **appid**: 用生成 token 的 Application ID
- **appidacr**: Application Authentication Context Class Reference指示客户端如何被认证对于 public client 值为 0若使用 client secret 则值为 1
- **acr**: Authentication Context Class Reference 声明,当终端用户的认证未满足 ISO/IEC 29115 要求时为 "0"。
- **amr**: Authentication method指示 token 的认证方式。值为 “pwd” 表示使用了密码。
- **groups**: 指示主体所属的组
- **iss**: 指示生成该 token 的 security token service (STS)。例如 https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/uuid 为 tenant ID
- **oid**: 主体的 object ID
- **tid**: Tenant ID
- **iat, nbf, exp**: Issued at签发时间Not before不可在此时间之前使用,通常与 iat 相同)Expiration time过期时间
## FOCI 令牌特权提升
之前提到过,刷新令牌应与生成时的 **scopes**、**应用程序**和 **租户** 绑定。如果打破了这些边界,可能会提升特权,因为将能够生成访问其他资源和租户的访问令牌,用户可以访问这些资源,并且具有比最初预期更多的范围。
## FOCI Tokens Privilege Escalation
此外,**所有刷新令牌都可以这样做** 在 [Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/)Microsoft Entra 账户、Microsoft 个人账户以及 Facebook 和 Google 等社交账户)中,因为正如 [**文档**](https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens) 所提到的:“刷新令牌绑定于用户和客户端的组合,但 **不绑定于资源或租户**。客户端可以使用刷新令牌获取 **在其有权限的任何资源和租户组合** 中的访问令牌。刷新令牌是加密的,只有 Microsoft identity platform 可以读取它们。”
前文提到 refresh tokens 应该与其生成时的 **scopes**、生成时的 **application****tenant** 绑定。如果这些边界中的任何一个被破坏,就可能发生权限提升 —— 可以生成对用户有访问权限的其他资源和 tenant 的 access tokens且可能比最初预期拥有更多的 scopes。
此外,请注意 FOCI 应用程序是公共应用程序,因此 **不需要密钥** 来进行服务器身份验证。
此外,在 [Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/)Microsoft Entra accounts、Microsoft personal accounts以及像 Facebook 和 Google 这样的 social accounts**所有 refresh tokens 都可能发生这种情况**,因为如 [**docs**](https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens) 所述“Refresh tokens are bound to a combination of user and client, but **aren't tied to a resource or tenant**. A client can use a refresh token to acquire access tokens **across any combination of resource and tenant** where it has permission to do so. Refresh tokens are encrypted and only the Microsoft identity platform can read them.”
然后在 [**原始研究**](https://github.com/secureworks/family-of-client-ids-research/tree/main) 中报告的已知 FOCI 客户端可以 [**在这里找到**](https://github.com/secureworks/family-of-client-ids-research/blob/main/known-foci-clients.csv)
另外,注意 FOCI applications 是 public applications所以**不需要 secret**即可向服务器进行认证
### 获取不同的范围
在 [**original research**](https://github.com/secureworks/family-of-client-ids-research/tree/main) 中报告的已知 FOCI clients 可在 [**found here**](https://github.com/secureworks/family-of-client-ids-research/blob/main/known-foci-clients.csv) 找到。
继续之前的示例代码,在此代码中请求了一个不同范围的新令牌:
### Get different scope
延续前面的示例代码,下面这段代码请求了一个用于不同 scope 的新 token
```python
# Code from https://github.com/secureworks/family-of-client-ids-research
azure_cli_bearer_tokens_for_outlook_api = (
@@ -185,7 +186,7 @@ scopes=[
)
pprint(azure_cli_bearer_tokens_for_outlook_api)
```
### 获取不同的客户端和范围
### 获取不同的 client 和 scopes
```python
# Code from https://github.com/secureworks/family-of-client-ids-research
microsoft_office_client = msal.PublicClientApplication("d3590ed6-52b3-4102-aeff-aad2292ab01c")
@@ -201,27 +202,28 @@ scopes=["https://graph.microsoft.com/.default"],
# How is this possible?
pprint(microsoft_office_bearer_tokens_for_graph_api)
```
## 找到令牌的地方
## 在哪里可以找到 tokens
从攻击者的角度来看,了解在受害者的PC被攻破时在哪里可以找到访问令牌和刷新令牌是非常有趣的
从攻击者的角度,当受害者的 PC 被攻破时,了解在哪里能够找到 access 和 refresh tokens 非常有价值
- **`<HOME>/.Azure`**
- 位于 **`<HOME>/.Azure`**
- **`azureProfile.json`** 包含过去登录用户的信息
- **`clouds.config` 包含** 订阅的信息
- **`service_principal_entries.json`** 包含应用程序凭据租户ID、客户端和密钥。仅在LinuxmacOS
- **`msal_token_cache.json`** 包含访问令牌和刷新令牌。仅在LinuxmacOS
- **`service_principal_entries.bin`** 和 **`msal_token_cache.bin`** 在Windows中使用,并使用DPAPI加密
- **`msal_http_cache.bin`** 是HTTP请求的缓存
- 加载 `with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)`
- **`AzureRmContext.json`** 包含使用Az PowerShell的先前登录信息(但没有凭据
-**`C:\Users\<username>\AppData\Local\Microsoft\IdentityCache\*`** 中有几`.bin` 文件,包含使用用户DPAPI加密的 **访问令牌**、ID令牌和帐户信息
- 可以在 **`C:\Users\<username>\AppData\Local\Microsoft\TokenBroken\Cache\`** 中的 `.tbres` 文件找到更多 **访问令牌**这些文件包含使用DPAPI加密的访问令牌的base64
- 在LinuxmacOS中,可以通过运行 `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"` 从Az PowerShell如果使用获取 **访问令牌、刷新令牌和ID令牌**
- 在Windows中,这只会生成ID令牌
- 可以通过检查 `$HOME/.local/share/.IdentityService/` 是否存在来查看是否在LinuxmacOS中使用了Az PowerShell尽管包含的文件是空的且无用)
- 如果用户浏览器**登录了Azure**,根据这篇 [**文章**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web),可以通过 **重定向到localhost** 开始身份验证流程,使浏览器自动授权登录,并接收刷新令牌。请注意,只有少数几个FOCI应用程序允许重定向到localhostaz cli或PowerShell模块因此必须允许这些应用程序
- **`clouds.config contains`** 包含有关订阅的信息
- **`service_principal_entries.json`** 包含应用凭证 (tenant id, clients and secret)。仅在 Linux & macOS
- **`msal_token_cache.json`** 包含 access tokens 和 refresh tokens。仅在 Linux & macOS
- **`service_principal_entries.bin`** 和 msal_token_cache.bin 在 Windows 上使用并受 DPAPI 加密
- **`msal_http_cache.bin`** 是 HTTP 请求的缓存
- 加载方式 `with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)`
- **`AzureRmContext.json`** 包含使用 Az PowerShell 的历史登录信息(但不含凭证
-**`C:\Users\<username>\AppData\Local\Microsoft\IdentityCache\*`** 下有多`.bin` 文件,包含 **access tokens**、ID tokens 和账户信息,均用用户的 DPAPI 加密
- 可以在 **`C:\Users\<username>\AppData\Local\Microsoft\TokenBroken\Cache\`** 中的 `.tbres` 文件找到更多 **access tokens**这些文件包含用 DPAPI 加密并 base64 编码的 access tokens
- LinuxmacOS 上,如果使用了 Az PowerShell运行 `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"` 来获取 **access tokens, refresh tokens and id tokens**
- Windows这只会生成 id tokens
- 可以通过检查 `$HOME/.local/share/.IdentityService/` 是否存在来判断在 LinuxmacOS 上是否使用过 Az PowerShell尽管其中的文件为空且没用)
- 如果用户使用浏览器登录了 Azure根据这篇 [**post**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web),可以重定向到 localhost 的方式启动认证流程,使浏览器自动授权登录,并接收 refresh token。注意,只有少数 FOCI 应用允许重定向到 localhost例如 az cli 或 powershell 模块),因此这些应用必须允许。
- 博客中解释的另一种方法是使用工具 [**BOF-entra-authcode-flow**](https://github.com/sudonoodle/BOF-entra-authcode-flow),它可以使用任何应用,因为它会 **获取 OAuth code然后从最终认证页面标题中取得 refresh token**,使用 redirect URI `https://login.microsoftonline.com/common/oauth2/nativeclient`
## 参考文献
## References
- [https://github.com/secureworks/family-of-client-ids-research](https://github.com/secureworks/family-of-client-ids-research)
- [https://github.com/Huachao/azure-content/blob/master/articles/active-directory/active-directory-token-and-claims.md](https://github.com/Huachao/azure-content/blob/master/articles/active-directory/active-directory-token-and-claims.md)