ID | Technique | Tactic |
---|---|---|
T1078 | Valid Accounts | Defense Evasion |
Detection: M365 Copilot Session Origin Anomalies
Description
Detects M365 Copilot users accessing from multiple geographic locations to identify potential account compromise, credential sharing, or impossible travel patterns. The detection aggregates M365 Copilot Graph API events per user, calculating distinct cities and countries accessed, unique IP addresses, and the observation timeframe to compute a locations-per-day metric that measures geographic mobility. Users accessing Copilot from more than one city (cities_count > 1) are flagged and sorted by country and city diversity, surfacing accounts exhibiting anomalous geographic patterns that suggest compromised credentials being used from distributed locations or simultaneous access from impossible travel distances.
Search
1`m365_copilot_graph_api` (appDisplayName="*Copilot*" OR appDisplayName="M365ChatClient" OR appDisplayName="OfficeAIAppChatCopilot")
2| eval user = userPrincipalName
3| stats count as events, dc(location.city) as cities_count, values(location.city) as city_list, dc(location.countryOrRegion) as countries_count, values(location.countryOrRegion) as country_list, dc(ipAddress) as ip_count, values(ipAddress) as ip_addresses, min(_time) as first_seen, max(_time) as last_seen by user
4| eval days_active = round((last_seen - first_seen)/86400, 1)
5| eval locations_per_day = if(days_active > 0, round(cities_count/days_active, 2), cities_count)
6| eval first_seen = strftime(first_seen, "%Y-%m-%d %H:%M:%S")
7| eval last_seen = strftime(last_seen, "%Y-%m-%d %H:%M:%S")
8| where cities_count > 1
9| sort -countries_count, -cities_count
10| `m365_copilot_session_origin_anomalies_filter`
Data Source
Name | Platform | Sourcetype | Source |
---|---|---|---|
M365 Copilot Graph API | N/A | 'o365:graph:api' |
'AuditLogs.SignIns' |
Macros Used
Name | Value |
---|---|
m365_copilot_graph_api | (sourcetype="o365:graph:api" OR source="AuditLogs.SignIns") |
m365_copilot_session_origin_anomalies_filter | search * |
m365_copilot_session_origin_anomalies_filter
is an empty macro by default. It allows the user to filter out any results (false positives) without editing the SPL.
Annotations
Default Configuration
This detection is configured by default in Splunk Enterprise Security to run with the following settings:
Setting | Value |
---|---|
Disabled | true |
Cron Schedule | 0 * * * * |
Earliest Time | -70m@m |
Latest Time | -10m@m |
Schedule Window | auto |
Creates Risk Event | True |
Implementation
This detection requires ingesting M365 Copilot access logs via the Splunk Add-on for Microsoft Office 365. Configure the add-on to collect Azure AD Sign-in logs (AuditLogs.SignIns) through the Graph API data input. Ensure proper authentication and permissions are configured to access sign-in audit logs. The m365_copilot_graph_api
macro should be defined to filter for sourcetype o365:graph:api data containing Copilot application activity.
Known False Positives
Legitimate business travelers, remote workers using VPNs, users with corporate offices in multiple locations, or employees accessing Copilot during international travel may trigger false positives.
Associated Analytic Story
Risk Based Analytics (RBA)
Risk Message:
User $user$ accessed M365 Copilot from multiple geographic locations, indicating potential account compromise or credential sharing.
Risk Object | Risk Object Type | Risk Score | Threat Objects |
---|---|---|---|
user | user | 10 | No Threat Objects |
References
Detection Testing
Test Type | Status | Dataset | Source | Sourcetype |
---|---|---|---|---|
Validation | ✅ Passing | N/A | N/A | N/A |
Unit | ✅ Passing | Dataset | AuditLogs.SignIns |
o365:graph:api |
Integration | ✅ Passing | Dataset | AuditLogs.SignIns |
o365:graph:api |
Replay any dataset to Splunk Enterprise by using our replay.py
tool or the UI.
Alternatively you can replay a dataset into a Splunk Attack Range
Source: GitHub | Version: 1