Microsoft Entra ID Suspicious Session Reuse to Graph Access

Identifies potential session hijacking or token replay in Microsoft Entra ID. This rule detects cases where a user signs in and subsequently accesses Microsoft Graph from a different IP address using the same session ID. This may indicate a successful OAuth phishing attack, session hijacking, or token replay attack, where an adversary has stolen a session cookie or refresh/access token and is impersonating the user from an alternate host or location.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2025/05/08"
  3integration = ["azure"]
  4maturity = "production"
  5updated_date = "2025/08/20"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10Identifies potential session hijacking or token replay in Microsoft Entra ID. This rule detects cases where a user signs
 11in and subsequently accesses Microsoft Graph from a different IP address using the same session ID. This may indicate a
 12successful OAuth phishing attack, session hijacking, or token replay attack, where an adversary has stolen a session
 13cookie or refresh/access token and is impersonating the user from an alternate host or location.
 14"""
 15false_positives = [
 16    """
 17    This pattern may occur during legitimate device switching or roaming between networks (e.g., corporate to mobile).
 18    Developers or power users leveraging multiple environments may also trigger this detection if session persistence
 19    spans IP ranges. Still, this behavior is rare and warrants investigation when rapid IP switching and Graph access
 20    are involved.
 21    """,
 22]
 23from = "now-31m"
 24interval = "30m"
 25language = "esql"
 26license = "Elastic License v2"
 27name = "Microsoft Entra ID Suspicious Session Reuse to Graph Access"
 28note = """## Triage and analysis
 29
 30### Investigating Microsoft Entra ID Suspicious Session Reuse to Graph Access
 31
 32Identifies potential phishing, session hijacking or token replay in Microsoft Entra ID. This rule detects cases where a user signs in and subsequently accesses Microsoft Graph from a different IP address using the same session ID and client application. This may indicate a successful OAuth phishing attack, session hijacking, or token replay attack, where an adversary has stolen a session cookie or refresh/access token and is impersonating the user from an alternate host or location.
 33
 34This rule uses ESQL aggregations and thus has dynamically generated fields. Correlation of the values in the alert document may need to be
 35performed to the original sign-in and Graph events for further context.
 36
 37### Possible investigation steps
 38
 39- This rule relies on an aggregation-based ESQL query, therefore the alert document will contain dynamically generated fields.
 40    - To pivot into the original events, it is recommended to use the values captured to filter in timeline or discovery for the original sign-in and Graph events.
 41- Review the session ID and user ID to identify the user account involved in the suspicious activity.
 42- Check the source addresses involved in the sign-in and Graph access to determine if they are known or expected locations for the user.
 43    - The sign-in source addresses should be two, one for the initial phishing sign-in and the other when exchanging the auth code for a token by the adversary.
 44    - The Graph API source address should identify the IP address used by the adversary to access Microsoft Graph.
 45- Review the user agent strings for the sign-in and Graph access events to identify any anomalies or indicators of compromise.
 46- Analyze the Graph permission scopes to identify what resources were accessed and whether they align with the user's expected behavior.
 47- Check the timestamp difference between the sign-in and Graph access events to determine if they occurred within a reasonable time frame that would suggest successful phishing to token issuance and then Graph access.
 48- Identify the original sign-in event to investigation if conditional access policies were applied, such as requiring multi-factor authentication or blocking access from risky locations. In phishing scenarios, these policies likely were applied as the victim user would have been prompted to authenticate.
 49
 50### False positive analysis
 51- This pattern may occur during legitimate device switching or roaming between networks (e.g., corporate to mobile).
 52- Developers or power users leveraging multiple environments may also trigger this detection if session persistence spans IP ranges. Still, this behavior is rare and warrants investigation when rapid IP switching and Graph access are involved.
 53
 54### Response and remediation
 55
 56- If confirmed malicious, revoke all refresh/access tokens for the user principal.
 57- Block the source IP(s) involved in the Graph access.
 58- Notify the user and reset credentials.
 59- Review session control policies and conditional access enforcement.
 60- Monitor for follow-on activity, such as lateral movement or privilege escalation.
 61- Review conditional access policies to ensure they are enforced correctly.
 62"""
 63references = [
 64    "https://www.volexity.com/blog/2025/04/22/phishing-for-codes-russian-threat-actors-target-microsoft-365-oauth-workflows/",
 65    "https://github.com/dirkjanm/ROADtools",
 66    "https://attack.mitre.org/techniques/T1078/004/",
 67]
 68risk_score = 47
 69rule_id = "0d3d2254-2b4a-11f0-a019-f661ea17fbcc"
 70setup = """#### Required Microsoft Entra ID Sign-In and Graph Activity Logs
 71This rule requires the Microsoft Entra ID Sign-In Logs and Microsoft Graph Activity Logs integration to be enabled and configured to collect audit and activity logs via Azure Event Hub.
 72"""
 73severity = "medium"
 74tags = [
 75    "Domain: Cloud",
 76    "Domain: Identity",
 77    "Domain: API",
 78    "Data Source: Azure",
 79    "Data Source: Microsoft Entra ID",
 80    "Data Source: Microsoft Entra ID Sign-In Logs",
 81    "Data Source: Microsoft Graph",
 82    "Data Source: Microsoft Graph Activity Logs",
 83    "Use Case: Identity and Access Audit",
 84    "Use Case: Threat Detection",
 85    "Resources: Investigation Guide",
 86    "Tactic: Defense Evasion",
 87    "Tactic: Initial Access",
 88]
 89timestamp_override = "event.ingested"
 90type = "esql"
 91
 92query = '''
 93from logs-azure.signinlogs-*, logs-azure.graphactivitylogs-* metadata _id, _version, _index
 94| where
 95    (event.dataset == "azure.signinlogs"
 96     and source.`as`.organization.name != "MICROSOFT-CORP-MSN-AS-BLOCK"
 97     and azure.signinlogs.properties.session_id is not null)
 98    or
 99    (event.dataset == "azure.graphactivitylogs"
100     and source.`as`.organization.name != "MICROSOFT-CORP-MSN-AS-BLOCK"
101     and azure.graphactivitylogs.properties.c_sid is not null)
102
103| eval
104    Esql.azure_signinlogs_properties_session_id_coalesce = coalesce(azure.signinlogs.properties.session_id, azure.graphactivitylogs.properties.c_sid),
105    Esql.azure_signinlogs_properties_user_id_coalesce = coalesce(azure.signinlogs.properties.user_id, azure.graphactivitylogs.properties.user_principal_object_id),
106    Esql.azure_signinlogs_properties_app_id_coalesce = coalesce(azure.signinlogs.properties.app_id, azure.graphactivitylogs.properties.app_id),
107    Esql.source_ip = source.ip,
108    Esql.@timestamp = @timestamp,
109    Esql.event_type_case = case(
110        event.dataset == "azure.signinlogs", "signin",
111        event.dataset == "azure.graphactivitylogs", "graph",
112        "other"
113    )
114
115| where Esql.azure_signinlogs_properties_app_id_coalesce not in (
116    "4354e225-50c9-4423-9ece-2d5afd904870",  // Augmentation Loop
117    "cc15fd57-2c6c-4117-a88c-83b1d56b4bbe",  // Microsoft Teams Services
118    "ecd6b820-32c2-49b6-98a6-444530e5a77a",  // Microsoft Edge [Community Contributed]
119    "e8be65d6-d430-4289-a665-51bf2a194bda",  // Microsoft 365 App Catalog Services
120    "ab9b8c07-8f02-4f72-87fa-80105867a763",  // OneDrive SyncEngine
121    "394866fc-eedb-4f01-8536-3ff84b16be2a",  // Microsoft People Cards Service
122    "66a88757-258c-4c72-893c-3e8bed4d6899",  // Office 365 Search Service
123    "9ea1ad79-fdb6-4f9a-8bc3-2b70f96e34c7",  // Bing
124    "d7b530a4-7680-4c23-a8bf-c52c121d2e87",  // Microsoft Edge Enterprise New Tab Page [Community Contributed]
125    "6f7e0f60-9401-4f5b-98e2-cf15bd5fd5e3",  // Microsoft Application Command Service [Community Contributed]
126    "52c2e0b5-c7b6-4d11-a89c-21e42bcec444",  // Graph Files Manager
127    "27922004-5251-4030-b22d-91ecd9a37ea4",  // Outlook Mobile
128    "bb893c22-978d-4cd4-a6f7-bb6cc0d6e6ce",  // Olympus [Community Contributed]
129    "26a7ee05-5602-4d76-a7ba-eae8b7b67941",  // Windows Search
130    "66a88757-258c-4c72-893c-3e8bed4d6899",  // Office 365 Search Service
131    "9ea1ad79-fdb6-4f9a-8bc3-2b70f96e34c7",  // Bing
132    "d7b530a4-7680-4c23-a8bf-c52c121d2e87",  // Microsoft Edge Enterprise New Tab Page [Community Contributed]
133    "00000007-0000-0000-c000-000000000000",  // Dataverse
134    "6bc3b958-689b-49f5-9006-36d165f30e00",  // Teams CMD Services Artifacts
135    "0ec893e0-5785-4de6-99da-4ed124e5296c",  // Office UWP PWA [Community Contributed]
136    "fc108d3f-543d-4374-bbff-c7c51f651fe5",  // Zoom
137    "01fc33a7-78ba-4d2f-a4b7-768e336e890e"   // MS PIM
138    )
139
140| keep
141    Esql.azure_signinlogs_properties_session_id_coalesce,
142    Esql.source_ip,
143    Esql.@timestamp,
144    Esql.event_type_case,
145    Esql.azure_signinlogs_properties_user_id_coalesce,
146    Esql.azure_signinlogs_properties_app_id_coalesce,
147    source.`as`.organization.name,
148    user_agent.original,
149    url.original,
150    azure.graphactivitylogs.properties.scopes,
151    azure.signinlogs.properties.user_principal_name
152
153| stats
154    Esql.azure_signinlogs_properties_user_id_coalesce_values = values(Esql.azure_signinlogs_properties_user_id_coalesce),
155    Esql.azure_signinlogs_properties_session_id_coalesce_values = values(Esql.azure_signinlogs_properties_session_id_coalesce),
156    Esql_priv.azure_signinlogs_properties_user_principal_name_values = values(azure.signinlogs.properties.user_principal_name),
157    Esql.source_ip_values = values(Esql.source_ip),
158    Esql.source_ip_count_distinct = count_distinct(Esql.source_ip),
159    Esql.source_as_organization_name_values = values(source.`as`.organization.name),
160    Esql.user_agent_original_values = values(user_agent.original),
161    Esql.azure_signinlogs_properties_app_id_coalesce_values = values(Esql.azure_signinlogs_properties_app_id_coalesce),
162    Esql.azure_signinlogs_properties_app_id_coalesce_count_distinct = count_distinct(Esql.azure_signinlogs_properties_app_id_coalesce),
163    Esql.event_type_case_values = values(Esql.event_type_case),
164    Esql.event_type_case_count_distinct = count_distinct(Esql.event_type_case),
165    Esql.signin_time_min = min(case(Esql.event_type_case == "signin", Esql.@timestamp, null)),
166    Esql.graph_time_min = min(case(Esql.event_type_case == "graph", Esql.@timestamp, null)),
167    Esql.url_original_values = values(url.original),
168    Esql.azure_graphactivitylogs_properties_scopes_values = values(azure.graphactivitylogs.properties.scopes),
169    Esql.event_count = count()
170  by
171    Esql.azure_signinlogs_properties_session_id_coalesce,
172    Esql.azure_signinlogs_properties_app_id_coalesce,
173    Esql.azure_signinlogs_properties_user_id_coalesce
174
175| eval
176    Esql.event_signin_to_graph_delay_minutes_date_diff = date_diff("minutes", Esql.signin_time_min, Esql.graph_time_min),
177    Esql.event_signin_to_graph_delay_days_date_diff = date_diff("days", Esql.signin_time_min, Esql.graph_time_min)
178
179| where
180    Esql.event_type_case_count_distinct > 1 and
181    Esql.source_ip_count_distinct > 1 and
182    Esql.azure_signinlogs_properties_app_id_coalesce_count_distinct == 1 and
183    Esql.signin_time_min is not null and
184    Esql.graph_time_min is not null and
185    Esql.event_signin_to_graph_delay_minutes_date_diff >= 0 and
186    Esql.event_signin_to_graph_delay_days_date_diff == 0
187'''
188
189
190[[rule.threat]]
191framework = "MITRE ATT&CK"
192[[rule.threat.technique]]
193id = "T1078"
194name = "Valid Accounts"
195reference = "https://attack.mitre.org/techniques/T1078/"
196[[rule.threat.technique.subtechnique]]
197id = "T1078.004"
198name = "Cloud Accounts"
199reference = "https://attack.mitre.org/techniques/T1078/004/"
200
201
202
203[rule.threat.tactic]
204id = "TA0001"
205name = "Initial Access"
206reference = "https://attack.mitre.org/tactics/TA0001/"
207[[rule.threat]]
208framework = "MITRE ATT&CK"
209[[rule.threat.technique]]
210id = "T1550"
211name = "Use Alternate Authentication Material"
212reference = "https://attack.mitre.org/techniques/T1550/"
213[[rule.threat.technique.subtechnique]]
214id = "T1550.001"
215name = "Application Access Token"
216reference = "https://attack.mitre.org/techniques/T1550/001/"
217
218
219
220[rule.threat.tactic]
221id = "TA0005"
222name = "Defense Evasion"
223reference = "https://attack.mitre.org/tactics/TA0005/"

Triage and analysis

Investigating Microsoft Entra ID Suspicious Session Reuse to Graph Access

Identifies potential phishing, session hijacking or token replay in Microsoft Entra ID. This rule detects cases where a user signs in and subsequently accesses Microsoft Graph from a different IP address using the same session ID and client application. This may indicate a successful OAuth phishing attack, session hijacking, or token replay attack, where an adversary has stolen a session cookie or refresh/access token and is impersonating the user from an alternate host or location.

This rule uses ESQL aggregations and thus has dynamically generated fields. Correlation of the values in the alert document may need to be performed to the original sign-in and Graph events for further context.

Possible investigation steps

  • This rule relies on an aggregation-based ESQL query, therefore the alert document will contain dynamically generated fields.
    • To pivot into the original events, it is recommended to use the values captured to filter in timeline or discovery for the original sign-in and Graph events.
  • Review the session ID and user ID to identify the user account involved in the suspicious activity.
  • Check the source addresses involved in the sign-in and Graph access to determine if they are known or expected locations for the user.
    • The sign-in source addresses should be two, one for the initial phishing sign-in and the other when exchanging the auth code for a token by the adversary.
    • The Graph API source address should identify the IP address used by the adversary to access Microsoft Graph.
  • Review the user agent strings for the sign-in and Graph access events to identify any anomalies or indicators of compromise.
  • Analyze the Graph permission scopes to identify what resources were accessed and whether they align with the user's expected behavior.
  • Check the timestamp difference between the sign-in and Graph access events to determine if they occurred within a reasonable time frame that would suggest successful phishing to token issuance and then Graph access.
  • Identify the original sign-in event to investigation if conditional access policies were applied, such as requiring multi-factor authentication or blocking access from risky locations. In phishing scenarios, these policies likely were applied as the victim user would have been prompted to authenticate.

False positive analysis

  • This pattern may occur during legitimate device switching or roaming between networks (e.g., corporate to mobile).
  • Developers or power users leveraging multiple environments may also trigger this detection if session persistence spans IP ranges. Still, this behavior is rare and warrants investigation when rapid IP switching and Graph access are involved.

Response and remediation

  • If confirmed malicious, revoke all refresh/access tokens for the user principal.
  • Block the source IP(s) involved in the Graph access.
  • Notify the user and reset credentials.
  • Review session control policies and conditional access enforcement.
  • Monitor for follow-on activity, such as lateral movement or privilege escalation.
  • Review conditional access policies to ensure they are enforced correctly.

References

Related rules

to-top