Detection rules › Panther
Azure Microsoft Graph Single Session from Multiple IP Addresses
Detects when a user signs in to Microsoft Entra ID and subsequently accesses Microsoft Graph from a different IP address using the same session ID. This behavior may indicate OAuth application abuse, session hijacking, token replay attacks, or adversary-in-the-middle attacks where an attacker has obtained a valid session token and is using it from their own infrastructure.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Initial Access | T1078.004 Valid Accounts: Cloud Accounts |
| Stealth | T1078.004 Valid Accounts: Cloud Accounts |
| Lateral Movement | T1550.001 Use Alternate Authentication Material: Application Access Token |
Rules detecting the same action
Other rules on this platform that filter on the same API call or operation.
Rule body yaml
AnalysisType: rule
Filename: azure_graph_session_multiple_ips.py
RuleID: "Azure.Audit.GraphSessionMultipleIPs"
DisplayName: "Azure Microsoft Graph Single Session from Multiple IP Addresses"
Enabled: true
Status: Experimental
LogTypes:
- Azure.Audit
Severity: Medium
Threshold: 2
DedupPeriodMinutes: 60
Description: >
Detects when a user signs in to Microsoft Entra ID and subsequently accesses Microsoft Graph from
a different IP address using the same session ID. This behavior may indicate OAuth application abuse,
session hijacking, token replay attacks, or adversary-in-the-middle attacks where an attacker has
obtained a valid session token and is using it from their own infrastructure.
Tags:
- Initial Access
- Valid Accounts
- Use Alternate Authentication Material
Reports:
MITRE ATT&CK:
- TA0001:T1078
- TA0001:T1078.004
- TA0005:T1550
- TA0005:T1550.001
Runbook: |
1. Query Azure.Audit logs for all Microsoft Graph access events with properties:sessionId in the 4 hours around this alert to identify all source IP addresses, user agents, and accessed resources
2. Compare the geographic locations and ASN information for all distinct callerIpAddress values to determine if they represent different countries, cloud providers, or inconsistent network types
3. Review Azure.Audit logs for properties:userPrincipalName in the 7 days before this session to identify OAuth consent grants, new application registrations, risky sign-ins, or token issuance events that may indicate initial compromise
Reference: https://github.com/elastic/detection-rules/blob/main/rules/integrations/azure/initial_access_entra_id_graph_single_session_from_multiple_addresses.toml
SummaryAttributes:
- properties:userPrincipalName
- callerIpAddress
- properties:sessionId
- properties:appDisplayName
Tests:
- Name: Multiple IP Access to Same Microsoft Graph Session
ExpectedResult: true
Log:
{
"time": "2025-01-15 09:35:20.456",
"resourceId": "/tenants/tenant-123/providers/Microsoft.aadiam",
"operationName": "Sign-in activity",
"operationVersion": "1.0",
"category": "SignInLogs",
"tenantId": "tenant-123",
"resultType": "Success",
"resultSignature": "SUCCESS",
"durationMs": 0,
"callerIpAddress": "5.5.5.5",
"correlationId": "graph-session-002",
"Level": "4",
"properties":
{
"createdDateTime": "2025-01-15T09:35:20.4567890Z",
"userPrincipalName": "gandalf@lotr.com",
"userId": "user-123",
"ipAddress": "5.5.5.5",
"sessionId": "session-abc-123",
"resourceDisplayName": "Microsoft Graph",
"resourceId": "00000003-0000-0000-c000-111111111111",
"appDisplayName": "Custom Graph App",
"appId": "app-custom-789",
"userAgent": "python-requests/2.28.1",
"isInteractive": true,
"authenticationProtocol": "oAuth2",
"conditionalAccessStatus": "success",
},
"p_event_time": "2025-01-15 09:35:20.456",
"p_log_type": "Azure.Audit",
"p_parse_time": "2025-01-15 09:35:21.000",
"p_row_id": "row-456",
}
- Name: Non-Interactive Sign-In via NonInteractiveUserSignInLogs Category
ExpectedResult: false
Log:
{
"time": "2026-02-18 07:34:37.443",
"resourceId": "/tenants/18360841-3f87-44a6-8c9a-3ffc680611a0/providers/Microsoft.aadiam",
"operationName": "Sign-in activity",
"operationVersion": "1.0",
"category": "NonInteractiveUserSignInLogs",
"tenantId": "18360841-3f87-44a6-8c9a-3ffc680611a0",
"resultType": "0",
"resultSignature": "SUCCESS",
"durationMs": 0,
"callerIpAddress": "203.0.113.10",
"correlationId": "6d657aae-f797-466f-8b35-31eb5b7ffde2",
"Level": "4",
"properties":
{
"createdDateTime": "2026-02-18T07:32:50.552947800Z",
"userPrincipalName": "jane.doe@example.com",
"userId": "3b4e2783-2b5d-4f1f-a3d9-ddc0ed1c623f",
"ipAddress": "203.0.113.10",
"sessionId": "00baf379-e510-523f-1c0e-346163d4a768",
"resourceDisplayName": "Microsoft Graph",
"resourceId": "00000003-0000-0000-c000-000000000000",
"appDisplayName": "Custom App",
"appId": "app-noninteractive-test-999",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
"isInteractive": false,
"signInEventTypes": ["nonInteractiveUser"],
"authenticationProtocol": "none",
"conditionalAccessStatus": "notApplied",
},
"p_event_time": "2026-02-18 07:34:37.443",
"p_log_type": "Azure.Audit",
}
- Name: Whitelisted Office 365
ExpectedResult: false
Log:
{
"time": "2025-01-15 10:00:30.789",
"resourceId": "/tenants/tenant-456/providers/Microsoft.aadiam",
"operationName": "Sign-in activity",
"operationVersion": "1.0",
"category": "SignInLogs",
"tenantId": "tenant-456",
"resultType": "Success",
"resultSignature": "SUCCESS",
"durationMs": 0,
"callerIpAddress": "192.0.2.100",
"correlationId": "office365-001",
"Level": "4",
"properties":
{
"createdDateTime": "2025-01-15T10:00:30.7890123Z",
"userPrincipalName": "employee@company.com",
"userId": "user-456",
"ipAddress": "192.0.2.100",
"sessionId": "session-office-456",
"resourceDisplayName": "Microsoft Graph",
"resourceId": "00000003-0000-0000-c000-000000000000",
"appDisplayName": "Office 365",
"appId": "00000003-0000-0ff1-ce00-000000000000",
"userAgent": "Microsoft Office/16.0",
"isInteractive": true,
"authenticationProtocol": "oAuth2",
"conditionalAccessStatus": "success",
},
"p_event_time": "2025-01-15 10:00:30.789",
"p_log_type": "Azure.Audit",
}
Detection logic
Condition
not (properties.resourceDisplayName not contains "Microsoft Graph" or properties.appId in ["00000003-0000-0ff1-ce00-000000000000", "00000006-0000-0ff1-ce00-000000000000", "00b41c95-dab0-4487-9791-b9d2c32c80f2", "d3590ed6-52b3-4102-aeff-aad2292ab01c", "1fec8e78-bce4-4aaf-ab1b-5451cc387264", "5e3ce6c0-2b1f-4285-8d4b-75ee78787346", "cc15fd57-2c6c-4117-a88c-83b1d56b4bbe", "ab9b8c07-8f02-4f72-87fa-80105867a763", "ea5a67f6-b6f3-4338-b240-c655ddc3cc8e", "ecd6b820-32c2-49b6-98a6-444530e5a77a", "f44b1140-bc5e-48c6-8dc0-5cf5a53c0e34", "797f4846-ba00-4fd7-ba43-dac1f8f63013", "8edd93e1-2103-40b4-bd70-6e34e586362d", "c44b4083-3bb0-49c1-b47d-974e53cbdf3c", "04b07795-8ddb-461a-bbee-02f9e1bf7b46", "4962773b-9cdb-44cf-a8bf-237846a00ab7", "fc780465-2017-40d4-a0c5-307022471b92", "8ee8fdad-f234-4243-8f3b-15c294843740", "2793995e-0a7d-40d7-bd35-6968ba142197", "3f6aecb4-6dbf-4e45-9141-440abdced562", "7b7531ad-5926-4f2d-8a1d-38495ad33e17", "df77edef-903d-416b-bcc0-cc8b91af54ea", "8b3391f4-af01-4ee8-b4ea-9871b2499735", "f8f7a2aa-e116-4ba6-8aea-ca162cfa310d", "01fc33a7-78ba-4d2f-a4b7-768e336e890e", "bd11ca0f-4fd6-4bb7-a259-4a36693b6e13", "abc63b55-0325-4305-9e1e-3463b182a6dc", "eace8149-b661-472f-b40d-939f89085bd4", "b46c3ac5-9da6-418f-a849-0a07a10b3c6c", "0469d4cd-df37-4d93-8a61-f8c75b809164", "18fbca16-2224-45f6-85b0-f7bf2b39b3f3", "98db8bd6-0cc0-4e67-9de5-f187f1cd1b41", "6821c7a6-ae62-49ba-8669-3f2e72d8d803", "7eadcef8-456d-4611-9480-4fff72b8b9e2"])
not (properties.isInteractive is_null or category eq "NonInteractiveUserSignInLogs")
not (properties.sessionId is_null or properties.userPrincipalName is_null or properties.ipAddress is_null or resultSignature ne "SUCCESS")
Exclusions
Top-level NOT(...) conjuncts: predicates this rule actively suppresses.
| Field | Kind | Excluded values |
|---|---|---|
properties.resourceDisplayName | contains | Microsoft Graph |
properties.appId | in | 00000003-0000-0ff1-ce00-000000000000, 00000006-0000-0ff1-ce00-000000000000, 00b41c95-dab0-4487-9791-b9d2c32c80f2, 01fc33a7-78ba-4d2f-a4b7-768e336e890e, 0469d4cd-df37-4d93-8a61-f8c75b809164, 04b07795-8ddb-461a-bbee-02f9e1bf7b46, 18fbca16-2224-45f6-85b0-f7bf2b39b3f3, 1fec8e78-bce4-4aaf-ab1b-5451cc387264, 2793995e-0a7d-40d7-bd35-6968ba142197, 3f6aecb4-6dbf-4e45-9141-440abdced562, 4962773b-9cdb-44cf-a8bf-237846a00ab7, 5e3ce6c0-2b1f-4285-8d4b-75ee78787346, 6821c7a6-ae62-49ba-8669-3f2e72d8d803, 797f4846-ba00-4fd7-ba43-dac1f8f63013, 7b7531ad-5926-4f2d-8a1d-38495ad33e17, 7eadcef8-456d-4611-9480-4fff72b8b9e2, 8b3391f4-af01-4ee8-b4ea-9871b2499735, 8edd93e1-2103-40b4-bd70-6e34e586362d, 8ee8fdad-f234-4243-8f3b-15c294843740, 98db8bd6-0cc0-4e67-9de5-f187f1cd1b41, ab9b8c07-8f02-4f72-87fa-80105867a763, abc63b55-0325-4305-9e1e-3463b182a6dc, b46c3ac5-9da6-418f-a849-0a07a10b3c6c, bd11ca0f-4fd6-4bb7-a259-4a36693b6e13, c44b4083-3bb0-49c1-b47d-974e53cbdf3c, cc15fd57-2c6c-4117-a88c-83b1d56b4bbe, d3590ed6-52b3-4102-aeff-aad2292ab01c, df77edef-903d-416b-bcc0-cc8b91af54ea, ea5a67f6-b6f3-4338-b240-c655ddc3cc8e, eace8149-b661-472f-b40d-939f89085bd4, ecd6b820-32c2-49b6-98a6-444530e5a77a, f44b1140-bc5e-48c6-8dc0-5cf5a53c0e34, f8f7a2aa-e116-4ba6-8aea-ca162cfa310d, fc780465-2017-40d4-a0c5-307022471b92 |
category | eq | NonInteractiveUserSignInLogs |
properties.isInteractive | is_null | |
properties.ipAddress | is_null | |
properties.sessionId | is_null | |
properties.userPrincipalName | is_null | |
resultSignature | ne | SUCCESS |
Indicators
Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.
| Field | Kind | Values |
|---|---|---|
properties.resourceDisplayName | contains |
|
Output fields
Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.
| Field | Source |
|---|---|
userPrincipalName | properties.userPrincipalName |
sessionId | properties.sessionId |