Microsoft Entra ID Session Reuse with Suspicious 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 within a short time window. This may indicate the use of a stolen refresh/access token or session cookie to impersonate the user and interact with Microsoft services.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2025/05/08"
  3integration = ["azure"]
  4maturity = "production"
  5min_stack_comments = "Elastic ES|QL values aggregation is more performant in 8.16.5 and above."
  6min_stack_version = "8.17.0"
  7updated_date = "2025/05/08"
  8
  9[rule]
 10author = ["Elastic"]
 11description = """
 12Identifies potential session hijacking or token replay in Microsoft Entra ID. This rule detects cases where a user signs
 13in and subsequently accesses Microsoft Graph from a different IP address using the same session ID within a short time
 14window. This may indicate the use of a stolen refresh/access token or session cookie to impersonate the user and
 15interact with Microsoft services.
 16"""
 17false_positives = [
 18    """
 19    This pattern may occur during legitimate device switching or roaming between networks (e.g., corporate to mobile).
 20    Developers or power users leveraging multiple environments may also trigger this detection if session persistence
 21    spans IP ranges. Still, this behavior is rare and warrants investigation when rapid IP switching and Graph access
 22    are involved.
 23    """,
 24]
 25from = "now-1h"
 26language = "esql"
 27license = "Elastic License v2"
 28name = "Microsoft Entra ID Session Reuse with Suspicious Graph Access"
 29note = """## Triage and analysis
 30
 31### Investigating Microsoft Entra ID Session Reuse with Suspicious Graph Access
 32
 33This rule identifies when Microsoft Graph is accessed from a different IP than the one used for the original sign-in,
 34but using the same session ID within 5 minutes. This may suggest an adversary has stolen a session cookie or refresh/access
 35token and is impersonating the user from an alternate host or location.
 36
 37This rule uses ES|QL aggregations and thus has dynamically generated fields. Correlation of the values in the alert document may need to be
 38performed to the original sign-in and Graph events for further context.
 39
 40### Investigation Steps
 41
 42- Review the `user_id`, `session_id`, and `source_ip_list`. Confirm whether both IPs belong to the same user and geography.
 43- Check for inconsistencies in `client_id_list` (e.g., unknown apps) or user agents across correlated events.
 44- Investigate recent phishing reports or device infections for the `user_id`.
 45- Pivot to Entra ID `auditlogs` to see if a device was registered or privileges were modified.
 46- Review `graph_time` to determine what action was taken after the sign-in.
 47- Use the `session_id` to correlate with other logs in the same time window to identify any additional suspicious activity.
 48
 49### False Positive Analysis
 50- This pattern may occur if the user is switching between networks (e.g., corporate to mobile) or using a VPN.
 51- Developers or power users leveraging multiple environments may also trigger this detection if session persistence spans IP ranges.
 52- However, this behavior is rare and warrants investigation when rapid IP switching and Graph access are involved.
 53- If the user is a developer or automation engineer, validate if this behavior was for testing purposes.
 54- If the user is a system administrator, validate if this behavior was for administrative purposes.
 55
 56### Response Recommendations
 57
 58- If confirmed malicious, revoke all refresh/access tokens for the `user_id`.
 59- Block the source IP(s) involved in the Graph access.
 60- Notify the user and reset credentials.
 61- Review session control policies and conditional access enforcement.
 62- Monitor for follow-on activity, such as lateral movement or privilege escalation.
 63- Review conditional access policies to ensure they are enforced correctly.
 64"""
 65references = [
 66    "https://www.volexity.com/blog/2025/04/22/phishing-for-codes-russian-threat-actors-target-microsoft-365-oauth-workflows/",
 67    "https://github.com/dirkjanm/ROADtools",
 68    "https://attack.mitre.org/techniques/T1078/004/",
 69]
 70risk_score = 73
 71rule_id = "0d3d2254-2b4a-11f0-a019-f661ea17fbcc"
 72setup = """#### Required Microsoft Entra ID Sign-In and Graph Activity Logs
 73This 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.
 74"""
 75severity = "high"
 76tags = [
 77    "Domain: Cloud",
 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.*
 94| WHERE
 95    (event.dataset == "azure.signinlogs" AND source.`as`.organization.name != "MICROSOFT-CORP-MSN-AS-BLOCK" AND azure.signinlogs.properties.session_id IS NOT NULL)
 96    OR
 97    (event.dataset == "azure.graphactivitylogs" AND source.`as`.organization.name != "MICROSOFT-CORP-MSN-AS-BLOCK" AND azure.graphactivitylogs.properties.c_sid IS NOT NULL)
 98| EVAL
 99    session_id = COALESCE(azure.signinlogs.properties.session_id, azure.graphactivitylogs.properties.c_sid),
100    user_id = COALESCE(azure.signinlogs.properties.user_id, azure.graphactivitylogs.properties.user_principal_object_id),
101    client_id = COALESCE(azure.signinlogs.properties.app_id, azure.graphactivitylogs.properties.app_id),
102    source_ip = source.ip,
103    event_time = @timestamp,
104    event_type = CASE(
105        event.dataset == "azure.signinlogs", "signin",
106        event.dataset == "azure.graphactivitylogs", "graph",
107        "other"
108    ),
109    time_window = DATE_TRUNC(5 minutes, @timestamp)
110| KEEP session_id, source_ip, event_time, event_type, time_window, user_id, client_id
111| STATS
112    user_id = VALUES(user_id),
113    session_id = VALUES(session_id),
114    source_ip_list = VALUES(source_ip),
115    source_ip_count = COUNT_DISTINCT(source_ip),
116    client_id_list = VALUES(client_id),
117    application_count = COUNT_DISTINCT(client_id),
118    event_type_list = VALUES(event_type),
119    event_type_count = COUNT_DISTINCT(event_type),
120    event_start = MIN(event_time),
121    event_end = MAX(event_time),
122    signin_time = MIN(CASE(event_type == "signin", event_time, NULL)),
123    graph_time = MIN(CASE(event_type == "graph", event_time, NULL)),
124    document_count = COUNT()
125  BY session_id, time_window
126| EVAL
127    duration_minutes = DATE_DIFF("minutes", event_start, event_end),
128    signin_to_graph_delay_minutes = DATE_DIFF("minutes", signin_time, graph_time)
129| WHERE
130    event_type_count > 1 AND
131    source_ip_count > 1 AND
132    duration_minutes <= 5 AND
133    signin_time IS NOT NULL AND
134    graph_time IS NOT NULL AND
135    signin_to_graph_delay_minutes >= 0
136'''
137
138
139[[rule.threat]]
140framework = "MITRE ATT&CK"
141[[rule.threat.technique]]
142id = "T1078"
143name = "Valid Accounts"
144reference = "https://attack.mitre.org/techniques/T1078/"
145[[rule.threat.technique.subtechnique]]
146id = "T1078.004"
147name = "Cloud Accounts"
148reference = "https://attack.mitre.org/techniques/T1078/004/"
149
150
151
152[rule.threat.tactic]
153id = "TA0001"
154name = "Initial Access"
155reference = "https://attack.mitre.org/tactics/TA0001/"
156[[rule.threat]]
157framework = "MITRE ATT&CK"
158[[rule.threat.technique]]
159id = "T1550"
160name = "Use Alternate Authentication Material"
161reference = "https://attack.mitre.org/techniques/T1550/"
162[[rule.threat.technique.subtechnique]]
163id = "T1550.001"
164name = "Application Access Token"
165reference = "https://attack.mitre.org/techniques/T1550/001/"
166
167
168
169[rule.threat.tactic]
170id = "TA0005"
171name = "Defense Evasion"
172reference = "https://attack.mitre.org/tactics/TA0005/"

Triage and analysis

Investigating Microsoft Entra ID Session Reuse with Suspicious Graph Access

This rule identifies when Microsoft Graph is accessed from a different IP than the one used for the original sign-in, but using the same session ID within 5 minutes. This may suggest 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 ES|QL 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.

Investigation Steps

  • Review the user_id, session_id, and source_ip_list. Confirm whether both IPs belong to the same user and geography.
  • Check for inconsistencies in client_id_list (e.g., unknown apps) or user agents across correlated events.
  • Investigate recent phishing reports or device infections for the user_id.
  • Pivot to Entra ID auditlogs to see if a device was registered or privileges were modified.
  • Review graph_time to determine what action was taken after the sign-in.
  • Use the session_id to correlate with other logs in the same time window to identify any additional suspicious activity.

False Positive Analysis

  • This pattern may occur if the user is switching between networks (e.g., corporate to mobile) or using a VPN.
  • Developers or power users leveraging multiple environments may also trigger this detection if session persistence spans IP ranges.
  • However, this behavior is rare and warrants investigation when rapid IP switching and Graph access are involved.
  • If the user is a developer or automation engineer, validate if this behavior was for testing purposes.
  • If the user is a system administrator, validate if this behavior was for administrative purposes.

Response Recommendations

  • If confirmed malicious, revoke all refresh/access tokens for the user_id.
  • 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