SessionID Is the Key: A SOC Analyst’s Guide to Investigating Microsoft 365 AiTM Attacks…
Microsoft 365 identity attacks are becoming increasingly difficult to investigate because an attacker may not need malware or direct access…
SessionID Is the Key: A SOC Analyst’s Guide to Investigating Microsoft 365 AiTM Attacks (Storm-2755)
Microsoft 365 identity attacks are becoming increasingly difficult to investigate because an attacker may not need malware or direct access to an endpoint. By stealing an authenticated session through an Adversary-in-the-Middle (AiTM) attack, an attacker can operate through legitimate Microsoft 365 services and make the activity look like normal user behavior.
For SOC analysts, the key is to correlate authentication, SessionID, Microsoft Graph, and mailbox activity instead of investigating an IP address or sign-in event in isolation.
Recent threat research from Arctic Wolf Labs describes a Microsoft 365 AiTM campaign that uses this approach to compromise accounts and target users involved in financial workflows. The research provides useful threat context, while the investigation methodology below focuses on how a SOC analyst can hunt for similar activity in their own environment.
How Does the Attack Happen?
The attack generally begins with a phishing email designed to look legitimate. In the campaign documented by Arctic Wolf, voicemail-themed messages were used to redirect victims through multiple legitimate services before eventually reaching an attacker-controlled AiTM proxy.
The AiTM proxy sits between the victim and the legitimate Microsoft authentication service and relays the authentication process in real time.
The simplified attack flow is:

AiTM Attack Flow
The important point for SOC analysts is that the attacker may successfully use MFA while still obtaining a usable authenticated session. Therefore, simply confirming that MFA was completed does not necessarily mean the session is legitimate.
Arctic Wolf also observed compromised sessions being maintained through rotating residential proxy infrastructure, with the same SessionID appearing across different IP addresses, locations, and ASNs
The Common SOC Investigation Mistake
Microsoft Defender XDR generate an alert named “Suspicious Exchange Online Graph Reconnaissance Activity.”
The purpose of this type of detection is to identify suspicious Microsoft Graph activity that may indicate an attacker is attempting to understand the organization’s users and identify high-value targets.
One of the most common mistakes during investigation of such alerts is:

Common Mistakes During Investigation from Analyst
This can happen because the activity may appear in non-interactive sign-in telemetry rather than the interactive sign-in logs an analyst initially checks.
Another problem is that the attacker may continue using a compromised session from different residential proxy IPs.
Therefore: Do not stop the investigation because the alert IP is not present in SigninLogs.
Instead, determine whether the relevant telemetry is being ingested and pivot through the SessionID.
How Should We Investigate then ?
The following workflow focuses on four primary Microsoft 365 data sources:
AADNonInteractiveUserSignInLogsSigninLogsMicrosoftGraphActivityLogsOfficeActivity
The objective is to build a timeline around the suspicious SessionID.
Step 1: Start With AADNonInteractiveUserSignInLogs
What should we look for?
Look for authentication activity associated with the alert IP and identify the corresponding SessionID, user, application, location, User-Agent, and device information. The expected result is to identify the session associated with the suspicious activity and determine whether that SessionID appears elsewhere.
Search Using the Alert IP
AADNonInteractiveUserSignInLogs
| where IPAddress == "<Enter Alert IP here>"
| project-reorder TimeGenerated, SessionId, IncomingTokenType, UserPrincipalName, IPAddress, AppDisplayName, Location, ResultType, ResultSignature, ResultDescription, UserAgent, DeviceDetail
Once the SessionID is identified, use it as the primary pivot.
Search Using SessionID
AADNonInteractiveUserSignInLogs
| where SessionId == "<Enter SessionID here>"
| project-reorder TimeGenerated, SessionId, IncomingTokenType, UserPrincipalName, IPAddress, AppDisplayName, Location, ResultType, ResultSignature, ResultDescription, UserAgent, DeviceDetail
Step 2: If Non-Interactive Logs Are Missing, Use SigninLogs
If AADNonInteractiveUserSignInLogs is not available in the environment, use SigninLogs as an alternative investigation source.
What should we look for?
Look for suspicious AppDisplyaName: OfficeHome authentication activity, particularly:
ResultType == "90014"- Unusual browser/OS combinations
- Failure followed by successful authentication
- Same SessionID across the events
Search for AppDisplayName: OfficeHome + Erorr Code: 90014
SigninLogs
| where UserPrincipalName contains "<Enter UserPrincipalName here>"
| where AppDisplayName == "OfficeHome"
| extend OS = DeviceDetail.operatingSystem, Browser = DeviceDetail.browser
| where ResultType == "90014"
| project-reorder TimeGenerated, UserId, UserPrincipalName, AppDisplayName, SessionId, ResultType, OS, Browser, IPAddress, Location
| sort by TimeGenerated desc
Step 2.1: Check for Failure Followed by Successful Sign-In
A 90014 event should not automatically be treated as malicious. The next step is to determine whether a successful authentication occurred using the same user and SessionID.
let SigninData = SigninLogs
| where TimeGenerated >= ago(30d)
| where UserPrincipalName contains "<Enter UserPrincipalName here>" //or SessionId == "<Enter SessionID here>"
| where AppDisplayName == "OfficeHome" or AppDisplayName contains "Microsoft Outlook"
| extend OS = tostring(DeviceDetail.operatingSystem), Browser = tostring(DeviceDetail.browser)
| where ResultType in ("90014", "0");
let Failed = SigninData
| where ResultType == "90014"
| project FailureTime = TimeGenerated, UserPrincipalName, SessionId;
let MatchedFailures = Failed
| join kind=inner ( SigninData | where ResultType == "0"
| project SuccessTime = TimeGenerated, UserPrincipalName, SessionId ) on UserPrincipalName, SessionId
| where SuccessTime > FailureTime and SuccessTime <= FailureTime + 12h
| project UserPrincipalName, SessionId, FailureTime, SuccessTime;
SigninData
| join kind=inner MatchedFailures on UserPrincipalName, SessionId
| where TimeGenerated == FailureTime or TimeGenerated == SuccessTime
| extend EventType = iff(ResultType == "90014", "Failure", "Success")
| project TimeGenerated, EventType, UserPrincipalName, SessionId, ResultType, AppDisplayName, IPAddress, Location, OS, Browser
| sort by UserPrincipalName asc, SessionId asc, TimeGenerated asc
Investigation objective
The important question is not: “Did 90014 occur?” The important question is: “What happened to the same session after the failure?”
If the session subsequently authenticates successfully and later appears in Graph or mailbox activity, the investigation becomes significantly more interesting.
Step 3: Investigate MicrosoftGraphActivityLogs
Microsoft Graph activity is particularly important because the attacker may use Graph API to identify employees involved in sensitive business processes.
What should we look for?
Look for:
- Graph
/usersenumeration /me$top=999- Payroll, HR, Finance, Admin, Account -related keywords
- Automated User-Agents such as
axiosorPython
The campaign research published by Arctic Wolf identified Graph reconnaissance targeting users associated with financial workflows.
Query
MicrosoftGraphActivityLogs
| where SessionId == "<Enter SessionID here>" //or UserId contains "<Enter UserID here>"
| where RequestUri startswith "https://graph.microsoft.com/v1.0/" and (RequestUri endswith "$top=999" or RequestUri endswith "/me")
| extend HasSearchKeywords = RequestUri has_any ("payroll", "hr", "finance", "account", "admin"), HasUserAgent = UserAgent has_any ("axios", "Python")
| project-reorder TimeGenerated, HasSearchKeywords, HasUserAgent, UserId, SessionId, AppId, IPAddress, Location, RequestUri, RequestMethod, ResponseStatusCode, UserAgent
| sort by TimeGenerated desc
Investigation objective
Determine: Did the suspicious session perform reconnaissance to identify high-value users before accessing mailbox data?
Step 4: Investigate OfficeActivity
After identifying suspicious Graph activity, the next step is to determine whether the same session accessed mailbox data.
What should we look for?
Look for:
MailItemsAccessed- Same SessionID
- REST-based access
- Payroll, Finance, HR, Invoices, Payments, Banking -related folders
Query
OfficeActivity
| extend SessionID = tostring(AppAccessContext.AADSessionId), FolderPath = tostring(parse_json(Folders)[0].Path)
| where SessionID == "<Enter SessionID here>" //or UserId contains "<Enter UserPrincipalName here>"
| where UserAgent contains "Client=REST;" or ClientInfoString contains "Client=REST;"
| project-reorder TimeGenerated, Operation, SessionID, UserId, Client_IPAddress, ClientInfoString, AppId, Folder, FolderPath, ResultStatus
| sort by TimeGenerated desc
The purpose is to establish whether the session that performed reconnaissance also accessed sensitive mailbox information.
Step 5: Trace the Entire Session
Once a suspicious SessionID is identified, the fastest way to understand the activity is to correlate it across multiple data sources.
union SigninLogs, MicrosoftGraphActivityLogs, OfficeActivity, AADNonInteractiveUserSignInLogs
| extend AADSessionId_ = tostring(AppAccessContext.AADSessionId), Path_ = tostring(parse_json(Folders)[0].Path), APIId_ = tostring(AppAccessContext.APIId), ClientAppId_ = tostring(AppAccessContext.ClientAppId)
| extend SessionID = iff(isnotempty(SessionId), SessionId, AADSessionId_), SourceIP = iff(isnotempty(IPAddress), IPAddress, Client_IPAddress)
| extend EventName = iff(isnotempty(Operation), Operation, OperationName)
| extend Username = iff(isnotempty(UserPrincipalName), UserPrincipalName, UserId)
| where SessionID == "<Enter SessionID here>"
| project-reorder TimeGenerated, Type, EventName, SessionID, Username, SourceIP, AutonomousSystemNumber, Location, AppDisplayName, AppId, ResultType, ResultSignature, ResultDescription, UserAgent, RequestUri, RequestMethod, ResponseStatusCode, Scopes, IncomingTokenType
| sort by TimeGenerated desc
This provides a consolidated timeline of the suspicious session.
Recommended Response Actions
If the investigation confirms that an authenticated Microsoft 365 session has been compromised:
- Revoke Active Sessions and Reset the Password.
- Review and Reconfigure MFA.
- Implement Conditional Access Controls. (Phishing-Resistant MFA, Require Managed / Compliant Devices, Continuous Access Evaluation, Session Controls)
What Should the SOC Analyst Avoid?
Avoid making the following assumptions:
“The IP is not in SigninLogs, so there is no compromise.” Not necessarily. Check whether the activity exists in AADNonInteractiveUserSignInLogs or other identity telemetry.
“The user completed MFA, so the login is legitimate.” Not necessarily. An AiTM attack can relay the legitimate authentication process and capture session material.
“The IP changed, so this must be a different session.” Not necessarily. SessionID should be checked before treating the activity as unrelated.
“90014 means compromise.” Not by itself. Treat it as a correlation signal and investigate the surrounding session activity.
“There is no malware on the endpoint, so there is no incident.” Cloud identity compromise can occur with little or no traditional endpoint-malware footprint.
The biggest lesson for SOC analysts is simple: Do not investigate Microsoft 365 identity alerts using the IP address alone.
An attacker can change the source IP, location, ASN, or proxy infrastructure while continuing to operate through the same compromised session. The SessionID can become the bridge that connects these seemingly unrelated events. This approach allows the SOC to move from investigating an individual alert to reconstructing the complete attack story.
메타데이터
- post_id
- 66ca1b7da2ee
- slug
- sessionid-is-the-key-a-soc-analysts-guide-to-investigating-microsoft-365-aitm-attacks-66ca1b7da2ee
- url
- https://medium.com/@nikhilkurkure95/sessionid-is-the-key-a-soc-analysts-guide-to-investigating-microsoft-365-aitm-attacks-66ca1b7da2ee
- canonical_url
- https://medium.com/@nikhilkurkure95/sessionid-is-the-key-a-soc-analysts-guide-to-investigating-microsoft-365-aitm-attacks-66ca1b7da2ee
- author_url
- https://medium.com/@nikhilkurkure95
- status
- ok
- fetched_at
- 2026-08-23 23:14:00