11.3 Investigation Setup and Scoping

4-6 hours · Module 11

Investigation Setup and Scoping

Before running investigation queries, establish the workspace and define the scope. Skipping this step leads to disorganised evidence, missed indicators, and an investigation that cannot be reproduced or defended under audit.

Required role: Microsoft Sentinel Reader (minimum for query execution). Microsoft Sentinel Responder (for bookmark creation and incident updates). If you have Sentinel Contributor or above, both are covered.


Create the investigation bookmark folder

All evidence collected during this investigation will be saved as Sentinel hunting bookmarks tagged with the incident ID. This creates a traceable evidence chain.

Tagging convention for this investigation: Every bookmark you create during this module should include these tags: INC-2026-0227-001, aitm, and a tag for the investigation phase (e.g., email-analysis, signin-investigation, containment).


Identify available data sources

Before writing queries, confirm which tables contain data in your workspace. Run this against your own tenant:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// Verify data source availability for AiTM investigation
// Each table must return count > 0 for the investigation queries to work
union withsource=TableName
    SigninLogs,
    AADNonInteractiveUserSignInLogs,
    AuditLogs,
    CloudAppEvents,
    EmailEvents,
    EmailUrlInfo,
    UrlClickEvents
| where TimeGenerated > ago(1d)
| summarize EventCount = count() by TableName
| order by TableName asc

Verify: Every table returns EventCount > 0. If any table returns 0: the corresponding data connector is not configured or not delivering data. Check Module 8 for connector setup. You cannot investigate what you cannot see — a missing table is a blind spot.

If UrlClickEvents returns 0: Safe Links click tracking may not be enabled, or the events may be ingested through the Defender XDR connector into a different table name. Check: UrlClickEvents | count and DeviceEvents | where ActionType == "ClickedUrl" | count.

If CloudAppEvents returns 0: The Defender XDR connector may not be configured to ingest Cloud Apps data. Check the connector settings in Module 8.3.


Define the investigation time window

The initial alert fired at 09:17 UTC on 27 February. Set the investigation window to start 24 hours before the alert and extend to the current time:

1
2
3
4
// Investigation time parameters  use throughout this module
// Adjust InvestigationStart if you discover earlier activity
let InvestigationStart = datetime(2026-02-26T09:00:00Z);
let InvestigationEnd = now();

Start 24 hours before the alert because: the phishing emails may have been sent before the first click, earlier reconnaissance activity may exist, and the attacker infrastructure may have been tested against the tenant before the campaign launched.

Expand the window if the investigation reveals earlier activity. When you discover Wave 3 occurred on 28 February at 03:00, extend InvestigationEnd. When you discover the phishing emails were sent at 08:45 on 27 February, you confirm InvestigationStart is adequate.


Initial scoping queries

These queries establish the baseline: how big is this incident? Run them before deep-diving into any specific evidence trail.

Scope query 1: How many users received the phishing email?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// Find all recipients of emails from the phishing sender domain
EmailEvents
| where TimeGenerated > datetime(2026-02-26T09:00:00Z)
| where SenderFromDomain == "sharepoint-secure-verify.com"
    or SenderMailFromDomain == "sharepoint-secure-verify.com"
| summarize
    RecipientCount = dcount(RecipientEmailAddress),
    Recipients = make_set(RecipientEmailAddress, 50),
    EmailCount = count(),
    FirstEmail = min(TimeGenerated),
    LastEmail = max(TimeGenerated)

Expected result: A count of recipients and the time window of email delivery. If RecipientCount is 1, this may be targeted spearphishing. If RecipientCount is 10+, this is a campaign. The result drives the scope of the investigation — a campaign requires checking every recipient.

Scope query 2: How many users clicked the phishing URL?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// Find all users who clicked the phishing URL
UrlClickEvents
| where TimeGenerated > datetime(2026-02-26T09:00:00Z)
| where Url has "secure-portal-verify.com"
| summarize
    ClickerCount = dcount(AccountUpn),
    Clickers = make_set(AccountUpn, 50),
    ClickCount = count(),
    FirstClick = min(TimeGenerated),
    LastClick = max(TimeGenerated)

Expected result: The number of users who clicked. Every clicker is a potential compromise — each must be investigated individually in subsection 11.5.

Scope query 3: How many users had sign-ins from the attacker IP?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// Find all sign-ins from the suspected attacker IP
SigninLogs
| where TimeGenerated > datetime(2026-02-26T09:00:00Z)
| where IPAddress == "203.0.113.47"
| where ResultType == "0"  // Successful
| summarize
    CompromisedCount = dcount(UserPrincipalName),
    CompromisedUsers = make_set(UserPrincipalName, 50),
    SigninCount = count(),
    FirstSignin = min(TimeGenerated),
    LastSignin = max(TimeGenerated)

Expected result: The confirmed compromised accounts (at this stage — more may be discovered as the investigation progresses).


Document the initial scope

After running the three scoping queries, document the results as the first incident comment:

“INC-2026-0227-001 initial scope (27 Feb 09:30 UTC): [X] recipients received phishing email from sharepoint-secure-verify.com. [Y] users clicked the URL. [Z] users have confirmed sign-ins from attacker IP 203.0.113.47. Phishing campaign started [FirstEmail]. Investigation in progress.”

This comment establishes the baseline scope. As the investigation progresses, you will update it.


Set up Livestream monitoring

While you investigate, the attacker may still be active. Start a Livestream (Module 10.6) to monitor for new activity from the attacker IP and the compromised account:

1
2
3
4
// Livestream: monitor for new attacker activity during investigation
SigninLogs
| where IPAddress == "203.0.113.47"
| project TimeGenerated, UserPrincipalName, AppDisplayName, ResultType

Keep this Livestream running in a separate tab throughout the investigation. If new sign-ins appear while you are investigating, the attacker is still active — escalate containment priority.

Subsection artifact: The three scoping queries above. Save them. They are the first three queries in your AiTM investigation playbook — the queries you run within the first 10 minutes of any suspected AiTM incident to establish scope before deep-diving.

Try it yourself

Run the data source verification query against your own tenant. Confirm which tables are populated. If any investigation-critical tables return 0, identify the missing connector and note it as a gap. Then run the three scoping queries with modified parameters: replace the phishing domain and attacker IP with values relevant to your environment (or use the Northgate Engineering values against your lab data). The goal is to practice the 10-minute scoping workflow — the first thing you do on any incident.

What you should observe

The data source verification returns a count for each table. Any table with 0 events is a blind spot. The scoping queries may return 0 results in a lab (no real phishing campaign) — this is expected. The exercise builds the muscle memory for the scoping workflow: verify data → scope recipients → scope clickers → scope compromised accounts → document → start Livestream.


Knowledge check

Check your understanding

1. Your UrlClickEvents table returns 0 events. What does this mean for the investigation?

Safe Links click tracking is not enabled or not ingesting into your workspace. You cannot determine which users clicked the phishing URL from this table. Alternative: check EmailUrlInfo for URL presence in emails and correlate with SigninLogs for sign-ins from unknown IPs within a time window after email delivery. The investigation proceeds but with reduced confidence — you are inferring clicks from sign-in timing rather than observing them directly. Note this as a data gap in the investigation record.
No users clicked the phishing URL
The investigation cannot proceed
Safe Links blocked all clicks