Entra ID Federated Identity Credential Modified

Last updated a month ago on 2026-10-01
Created a year ago on 2025-07-14

About

Detects when a federated identity credential is added to an Entra ID application, or when the issuer or subject of an existing credential is changed. Adversaries with application-management rights can federate the application to an attacker-controlled identity provider, or re-scope an existing trust on a shared issuer such as GitHub Actions to an identity they control, and authenticate as its service principal without creating a client secret.
Tags
Domain: CloudDomain: IdentityData Source: AzureData Source: Microsoft Entra ID Audit LogsUse Case: Identity and Access AuditTactic: PersistenceTactic: Privilege EscalationTactic: Defense EvasionProfile: BetaRule Type: ES|QLPlatform: Entra IDLanguage: esql
Severity
high
Risk Score
73
MITRE ATT&CK™

Persistence (TA0003)(external, opens in a new tab or window)

Privilege Escalation (TA0004)(external, opens in a new tab or window)

Defense Evasion (TA0005)(external, opens in a new tab or window)

License
Elastic License v2(external, opens in a new tab or window)

Definition

Integration Pack
Prebuilt Security Detection Rules
Related Integrations

azure(external, opens in a new tab or window)

Query
text code block:
from logs-azure.auditlogs-* metadata _id, _version, _index | where event.action == "Update application" | where `azure.auditlogs.properties.target_resources.0.modified_properties.0.display_name` == "FederatedIdentityCredentials" | eval Esql.fic_old_value = `azure.auditlogs.properties.target_resources.0.modified_properties.0.old_value` | eval Esql.fic_new_value = `azure.auditlogs.properties.target_resources.0.modified_properties.0.new_value` // each credential is one JSON object, so the number of "{" is the credential count | eval Esql.fic_old_count = mv_count(split(Esql.fic_old_value, "{")) - 1 | eval Esql.fic_new_count = mv_count(split(Esql.fic_new_value, "{")) - 1 // removals never alert | where Esql.fic_new_count > 0 and Esql.fic_new_count >= Esql.fic_old_count // strip the outer brackets and expand the new array into one row per credential object | eval Esql.fic_object = split(replace(substring(Esql.fic_new_value, 2, length(Esql.fic_new_value) - 2), "\\},\\{", "}\n{"), "\n") | mv_expand Esql.fic_object | eval Esql.fic_id = json_extract(Esql.fic_object, "Id"), Esql.fic_new_issuer = json_extract(Esql.fic_object, "Issuer"), Esql.fic_new_subject = json_extract(Esql.fic_object, "Subject") // locate the same credential Id in the old array and rebuild that object to read its previous issuer and subject | eval Esql.fic_old_id_pos = locate(Esql.fic_old_value, concat("\"Id\":\"", Esql.fic_id, "\"")) | eval Esql.fic_old_object = case( Esql.fic_old_id_pos > 0, concat("{", mv_last(split(substring(Esql.fic_old_value, 1, Esql.fic_old_id_pos - 1), "{")), mv_first(split(substring(Esql.fic_old_value, Esql.fic_old_id_pos), "}")), "}"), null ) | eval Esql.fic_old_issuer = json_extract(Esql.fic_old_object, "Issuer"), Esql.fic_old_subject = json_extract(Esql.fic_old_object, "Subject") // subject is null on flexible credentials that use a claims matching expression, so coalesce before comparing | eval Esql.fic_change = case( Esql.fic_old_count == 0, "fic_created", Esql.fic_old_id_pos == 0 and Esql.fic_new_count > Esql.fic_old_count, "fic_added", Esql.fic_old_issuer != Esql.fic_new_issuer, "fic_issuer_changed", coalesce(Esql.fic_old_subject, "") != coalesce(Esql.fic_new_subject, ""), "fic_subject_changed", "none" ) | where Esql.fic_change != "none" // the raw old/new arrays stay on the alert under azure.*; drop the working copies and intermediates | drop Esql.fic_old_value, Esql.fic_new_value, Esql.fic_object, Esql.fic_old_object, Esql.fic_old_id_pos | keep @timestamp, Esql.*, azure.*, event.*, cloud.*, related.*, tags, source.*, agent.*, client.*, _id, _version, _index, data_stream.namespace

Install detection rules in Elastic Security

Detect Entra ID Federated Identity Credential Modified in the Elastic Security detection engine by installing this rule into your Elastic Stack.

To setup this rule, check out the installation guide for Prebuilt Security Detection Rules(external, opens in a new tab or window).