Skip to content

Commit c2880af

Browse files
[New Rule] OIDC Discovery URL Changed in Entra ID (#4908)
* new rule OIDC Discovery URL Changed in Entra ID * added references * removed indexes * Update rules/integrations/azure/persistence_entra_id_oidc_discovery_url_change.toml * adjusted for ESQL standardization
1 parent a3a2fcd commit c2880af

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
[metadata]
2+
creation_date = "2025/07/14"
3+
integration = ["azure"]
4+
maturity = "production"
5+
updated_date = "2025/07/14"
6+
7+
[rule]
8+
author = ["Elastic"]
9+
description = """
10+
Detects a change to the OpenID Connect (OIDC) discovery URL in the Entra ID Authentication Methods Policy. This behavior
11+
may indicate an attempt to federate Entra ID with an attacker-controlled identity provider, enabling bypass of
12+
multi-factor authentication (MFA) and unauthorized access through bring-your-own IdP (BYOIDP) methods.
13+
"""
14+
from = "now-9m"
15+
language = "esql"
16+
license = "Elastic License v2"
17+
name = "OIDC Discovery URL Changed in Entra ID"
18+
note = """## Triage and analysis
19+
20+
### Investigating OIDC Discovery URL Changed in Entra ID
21+
22+
This rule detects when the OIDC `discoveryUrl` is changed within the Entra ID Authentication Methods policy. Adversaries may leverage this to federate Entra ID with a rogue Identity Provider (IdP) under their control, allowing them to authenticate users with attacker-owned credentials and bypass MFA. This misconfiguration allows an attacker to impersonate valid users by issuing tokens via a third-party OIDC IdP while still passing validation in Entra ID. This technique has been publicly demonstrated and has critical implications for trust in federated identity.
23+
24+
### Possible investigation steps
25+
- Review `azure.auditlogs.properties.initiated_by.user.userPrincipalName` and `ipAddress` to identify who made the change and from where.
26+
- Examine the `old_oidc_discovery` and `new_oidc_discovery` to confirm if the new `discoveryUrl` points to an unexpected or untrusted IdP.
27+
- Check that the discovery URLs have `.well-known/openid-configuration` endpoints, which are standard for OIDC providers.
28+
- Use `azure.auditlogs.properties.correlation_id` to pivot to related changes and activity from the same session.
29+
- Review any subsequent sign-in activity that may have originated from the new IdP.
30+
- Pivot to additional logs associated with the user or application that made the change to identify any further suspicious activity.
31+
32+
### False positive analysis
33+
- Entra ID administrators may intentionally reconfigure OIDC trust relationships to support new business requirements.
34+
- Validate any changes with the identity or security operations team before taking action.
35+
36+
### Response and remediation
37+
- If the change is unauthorized, immediately revert the discovery URL to the trusted IdP via the Entra ID portal.
38+
- Revoke tokens or sessions issued after the configuration change.
39+
- Investigate how the unauthorized change occurred (e.g., compromised account or over-privileged app).
40+
- Apply conditional access policies and change control procedures to protect IdP configuration changes.
41+
"""
42+
references = ["https://dirkjanm.io/persisting-with-federated-credentials-entra-apps-managed-identities/"]
43+
risk_score = 73
44+
rule_id = "498e4094-60e7-11f0-8847-f661ea17fbcd"
45+
severity = "high"
46+
tags = [
47+
"Domain: Cloud",
48+
"Domain: Identity",
49+
"Data Source: Azure",
50+
"Data Source: Microsoft Entra ID",
51+
"Data Source: Microsoft Entra ID Audit Logs",
52+
"Use Case: Identity and Access Audit",
53+
"Tactic: Persistence",
54+
"Resources: Investigation Guide",
55+
]
56+
timestamp_override = "event.ingested"
57+
type = "query"
58+
59+
query = '''
60+
FROM logs-azure.auditlogs-*
61+
| WHERE event.action == "Authentication Methods Policy Update"
62+
| EVAL Esql.azure.auditlogs.properties.target_resources.modified_properties.new_value.replace = REPLACE(`azure.auditlogs.properties.target_resources.0.modified_properties.0.new_value`, "\\\\", "")
63+
| EVAL Esql.azure.auditlogs.properties.target_resources.modified_properties.old_value.replace = REPLACE(`azure.auditlogs.properties.target_resources.0.modified_properties.0.old_value`, "\\\\", "")
64+
| DISSECT Esql.azure.auditlogs.properties.target_resources.modified_properties.new_value.replace "%{}discoveryUrl\":\"%{Esql.azure.auditlogs.properties.auth.oidc.discovery.url.new}\"}%{}"
65+
| DISSECT Esql.azure.auditlogs.properties.target_resources.modified_properties.old_value.replace "%{}discoveryUrl\":\"%{Esql.azure.auditlogs.properties.auth.oidc.discovery.url.old}\"}%{}"
66+
| WHERE Esql.azure.auditlogs.properties.auth.oidc.discovery.url.new IS NOT NULL and Esql.azure.auditlogs.properties.auth.oidc.discovery.url.old IS NOT NULL
67+
| WHERE Esql.azure.auditlogs.properties.auth.oidc.discovery.url.new != Esql.azure.auditlogs.properties.auth.oidc.discovery.url.old
68+
| KEEP
69+
@timestamp,
70+
event.action,
71+
event.outcome,
72+
azure.tenant_id,
73+
azure.correlation_id,
74+
azure.auditlogs.properties.activity_datetime,
75+
azure.auditlogs.properties.operation_type,
76+
azure.auditlogs.properties.initiated_by.user.userPrincipalName,
77+
azure.auditlogs.properties.initiated_by.user.displayName,
78+
azure.auditlogs.properties.initiated_by.user.ipAddress,
79+
source.geo.city_name,
80+
source.geo.region_name,
81+
source.geo.country_name,
82+
Esql.azure.auditlogs.properties.auth.oidc.discovery.url.new,
83+
Esql.azure.auditlogs.properties.auth.oidc.discovery.url.old
84+
'''
85+
86+
87+
[[rule.threat]]
88+
framework = "MITRE ATT&CK"
89+
[[rule.threat.technique]]
90+
id = "T1556"
91+
name = "Modify Authentication Process"
92+
reference = "https://attack.mitre.org/techniques/T1556/"
93+
[[rule.threat.technique.subtechnique]]
94+
id = "T1556.009"
95+
name = "Conditional Access Policies"
96+
reference = "https://attack.mitre.org/techniques/T1556/009/"
97+
98+
99+
100+
[rule.threat.tactic]
101+
id = "TA0003"
102+
name = "Persistence"
103+
reference = "https://attack.mitre.org/tactics/TA0003/"
104+

0 commit comments

Comments
 (0)