Skip to content

This tool is not affiliated with, endorsed by or sponsored by Microsoft Corporation. Azure, Microsoft Azure and Microsoft Defender for Cloud are trademarks of the Microsoft group of companies. Other names are trademarks of their respective owners.

Managed identity and service principal abuse in Azure

How attackers abuse Azure service principals and managed identities: leaked secrets, IMDS token theft, federated credentials, runbooks, and the log signals.

Published on 6 min read

TL;DR. Non-human identities are the quiet majority of Azure callers, and the favourite disguise of intruders. Three patterns: a service principal whose secret leaked (CI/CD variables, a repo, a laptop) used from a new IP; a managed identity token taken from the VM's Instance Metadata Service (169.254.169.254) and replayed from elsewhere; and persistence through federated credentials, Automation runbooks, Logic Apps or Functions running as a privileged identity. In the logs, the xms_mirid claim marks a managed identity, and "same identity, new IP" is the strongest single signal you have.

When I review a compromised subscription, the human accounts are usually easy: few of them, predictable hours, MFA in the claims. The hard part is the dozens of application identities that call Azure Resource Manager all day. That is where attackers blend in.

Service principals and managed identities, in log terms

IdentityWhat it isHow it appears in Activity Log claims
Service principal (app registration)Application identity authenticated with a client secret, certificate or federated credentialappid + object ID, often idtyp: app; caller is a GUID
Managed identityService principal managed by Azure, bound to a resource (system-assigned) or standalone (user-assigned)Same, plus xms_mirid = resource ID of the VM / app / identity it belongs to
UserHuman accountUPN, name, amr (e.g. pwd, mfa)

The Azure Forensics analyzer classifies callers this way (claims first, then principalType, then GUID-shaped callers) and shows the type in the Entities tab. In Key Vault and storage logs the same claims appear under identity.claim and identity.requester.

Pattern 1: a leaked service principal secret

The initial access is outside Azure: a secret committed to a repository, printed in a CI log, or stolen from a developer's machine. Microsoft Entra ID sees the sign-in (service principal sign-in logs); Azure sees what follows.

Signals in Azure logs:

  • The SP calls ARM from an IP it never used before. CI runners have a small, stable set of IPs or a known cloud range; an attacker's VPS is neither.
  • The SP does something it never did: role assignments, Run Command, listKeys, access-policy changes.
  • Timing: deployment SPs run when pipelines run. A burst at 02:14 on a Sunday with no pipeline run is telling.

MITRE ATT&CK: T1078.004 Cloud Accounts. How the secret leaked, and whether new secrets were added to the application (T1098.001 Additional Cloud Credentials), is recorded in the Entra ID audit log — analysed by the sibling tool m365forensics.com.

Pattern 2: managed identity token theft via IMDS

Any process on a VM can ask the Instance Metadata Service for a token of the VM's managed identity:

GET http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/
Metadata: true

Microsoft states the security boundary plainly: "All code/scripts running on a virtual machine can request and retrieve tokens for any managed identities available on it" (Use managed identities on a VM to acquire an access token). The Metadata header is an SSRF mitigation, not an authorization check.

So code execution on a VM — through Run Command, a web shell or an SSRF that can set headers — becomes a cloud identity. The attacker copies the bearer token and uses it from their own machine until it expires (T1528 Steal Application Access Token).

The signal is simple and strong: a managed identity used from an IP that is not its host. A VM's managed identity normally reaches Key Vault and storage from the VM's private IP (through a service endpoint or private endpoint) or from a stable outbound public IP. The same object ID showing up with a residential or VPS address, and a curl user agent, is token replay.

Pattern 3: persistence through identities

Once an attacker has a privileged identity, they want one that survives password resets and secret rotation:

PersistenceActivity Log operationMITRE
Federated credential on a user-assigned managed identity (lets an external IdP get tokens for it)Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/writeT1098.001
Automation runbook or webhook, running as the Automation account's identityMicrosoft.Automation/automationAccounts/runbooks/write, …/webhooks/write, …/jobs/writeT1648
Logic App or Function code changedMicrosoft.Logic/workflows/write, Microsoft.Web/sites/functions/write, function keys writtenT1648
New secret or certificate on an app registrationEntra ID audit log, not the Activity LogT1098.001

Federated credentials are legitimate and common (GitHub Actions, AKS workload identity). The question is always: which issuer and subject, created by whom, and does anyone own it?

What the analyzer flags

RuleDetectsLevel
AZ-ID-001Service principal calls ARM from an IP not seen during the 72-hour learning periodMedium
AZ-ID-002Managed identity used from a new IP — Activity Log, Key Vault or storageHigh
AZ-RBAC-002Service principal or managed identity assigned Owner, Contributor or an access-management roleHigh
AZ-PER-001Automation runbook, webhook or job createdMedium
AZ-PER-002Logic App or Function code changedLow
AZ-PER-003Federated credential added to a managed identityHigh

"New IP" rules need history: with less than 72 hours of logs before the suspicious activity, they cannot run, and the coverage block says so. Known false positives: CI runners with changing IPs, VMs redeployed with a new private IP.

Triage checklist

  1. List every non-human identity with a finding in the Entities tab, then open each one's events.
  2. For each, establish the baseline: normal IPs, normal operations, normal hours. The first deviation is the start of your timeline.
  3. For a managed identity: which resource is it bound to (xms_mirid)? Was there code execution on that resource shortly before (Run Command, extension, deployment)?
  4. For a service principal: when was its last credential added, and by whom? (Entra audit log.)
  5. What did it touch? Key Vault reads, storage reads, role assignments. Each is a new branch of the investigation.

Remediation

  • Rotate the secrets and certificates of compromised service principals; remove credentials nobody owns.
  • A managed identity has no secret to rotate. Contain the host (isolate and rebuild the VM), and reduce the identity's role assignments. Access tokens already stolen stay valid until they expire, so keep watching the identity's activity from foreign IPs for a while — and rotate the secrets it could read.
  • Remove unknown federated credentials, runbooks and webhooks.
  • Reduce privileges: no subscription-wide Contributor for a web app's identity.

Related articles

How attackers use Azure VM Run Command and the Custom Script Extension, what the Activity Log records (and omits), and which on-VM artifacts hold the script.
How attackers escalate with Azure role assignments and elevateAccess, what roleAssignments/write events look like in the Activity Log, and how to triage them.
Think your Azure subscription is compromised? Which logs to preserve first, the operations that betray an attacker, and how to go from Activity Log to verdict.

This tool is not affiliated with, endorsed by or sponsored by Microsoft Corporation. Azure, Microsoft Azure and Microsoft Defender for Cloud are trademarks of the Microsoft group of companies. Other names are trademarks of their respective owners.