Agent Foskett Academy • KQL Academy • Module 11 • Lesson 140 • Module Finale

Lesson 140 — The Identity Threat Hunting Investigation

Nine lessons ago, we began with a simple question: was that sign-in really normal?

Since then we have investigated MFA fatigue, newly registered authentication methods, Conditional Access results, privileged role activation, shared source IPs, abnormal sessions, multi-table identity evidence and compromise timelines.

Now we put it together. This is a complete case. You are given the first clue; your job is to follow the evidence, challenge the working theory and decide what the telemetry actually supports.

Module 11 finale: do not investigate the alert. Investigate the identity.
Agent Foskett KQL Academy complete identity threat hunting investigation
Your case file

A successful sign-in appears after several failures. The source touches other accounts. Privileged and cloud activity follow.

✓ Establish initial access
✓ Test the source IP
✓ Hunt privilege and persistence
✓ Reach a defensible conclusion

Case briefing

CASE FILE Identity: alex.wilson@contoso.com ↓ 01:42 UTC — failed sign-in ↓ 01:48 — another failure ↓ 01:53 — SUCCESS ↓ 02:07 — privileged activity ↓ 02:16 — directory activity ↓ 02:21 — cloud actions begin ↓ YOUR TASK Determine whether these are unrelated events or one identity compromise.

Investigation objective

Determine whether the evidence supports legitimate activity, suspicious authentication without confirmed compromise, or likely identity compromise with post-authentication activity.

Investigator's rule

Do not begin with the conclusion. At every stage ask what the query proves, what it suggests and what evidence could disprove your working theory.

Stage 1 — establish the authentication story

Start with the identity. Keep failures, successes and access-control context together.

01-establish-authentication-story.kql
1234567891011121314
let TargetUser = "alex.wilson@contoso.com";
SigninLogs
| where TimeGenerated > ago(24h)
| where UserPrincipalName =~ TargetUser
| project TimeGenerated,
          UserPrincipalName,
          IPAddress,
          Location,
          AppDisplayName,
          ResultType,
          ResultDescription,
          ConditionalAccessStatus,
          AuthenticationRequirement
| order by TimeGenerated asc

What are you looking for?

Sequence. Did failures precede success? Did source, location or application change? Was MFA involved? What did Conditional Access actually report?

Do not over-read MFA

MFA satisfaction is evidence about an authentication requirement. It is not proof that the person operating the resulting session was the legitimate user.

Stage 2 — pivot from the user to the source

The IP address now becomes an investigative entity. Ask whether it touched other identities and whether the activity was concentrated.

02-investigate-source-ip.kql
1234567891011
let TargetIP = "203.0.113.42";
SigninLogs
| where TimeGenerated > ago(24h)
| where IPAddress == TargetIP
| summarize AttemptCount=count(),
            FailureCount=countif(ResultType != "0"),
            SuccessCount=countif(ResultType == "0"),
            UserCount=dcount(UserPrincipalName),
            Users=make_set(UserPrincipalName, 25)
          by bin(TimeGenerated, 10m)
| order by TimeGenerated asc

The investigation just widened

If the same source produces failures across several identities, the original event may be part of broader credential activity rather than an isolated user problem.

But shared IP does not equal attacker

Corporate egress, VPNs, proxies and carrier networks can represent many legitimate users. Interpret user count, timing, outcomes and network context together.

Stage 3 — hunt privilege and persistence

Examine directory audit activity around the identity. Look for operations that increase capability or could make future access easier.

03-hunt-privilege-and-persistence.kql
1234567891011
let TargetUser = "alex.wilson@contoso.com";
AuditLogs
| where TimeGenerated > ago(24h)
| where tostring(InitiatedBy) contains TargetUser
       or tostring(TargetResources) contains TargetUser
| project TimeGenerated,
          OperationName,
          ActivityDisplayName,
          InitiatedBy,
          TargetResources
| order by TimeGenerated asc

Ask who changed what

Preserve InitiatedBy and TargetResources. The account may be the actor, target or both.

Timing strengthens the hypothesis

A role or authentication-related change minutes after suspicious access is more interesting than the same operation days later. Chronology creates investigative context.

Stage 4 — investigate what happened after access

Where available, use CloudAppEvents to examine post-authentication cloud behaviour.

04-investigate-post-authentication-activity.kql
12345678910111213
let TargetUser = "alex.wilson@contoso.com";
CloudAppEvents
| where Timestamp > ago(24h)
| where AccountId =~ TargetUser
       or AccountDisplayName =~ TargetUser
| project Timestamp,
          Application,
          ActionType,
          ObjectName,
          IPAddress,
          CountryCode,
          City
| order by Timestamp asc

Impact lives after authentication

File, mailbox, sharing, application and administrative actions can establish whether the incident progressed beyond successful access.

Objects matter

Preserve the application, action and affected object where possible. A useful incident conclusion explains what the identity actually touched.

Stage 5 — build the complete evidence timeline

Shape the event streams into common fields, stack them with union and sort them chronologically.

05-build-complete-identity-timeline.kql
1234567891011121314151617181920212223242526272829303132333435363738394041
let TargetUser = "alex.wilson@contoso.com";
let SignIns =
    SigninLogs
    | where TimeGenerated > ago(24h)
    | where UserPrincipalName =~ TargetUser
    | project EventTime=TimeGenerated,
              SourceTable="SigninLogs",
              EventType="Sign-in",
              Detail=AppDisplayName,
              IPAddress;
let IdentityEvents =
    IdentityLogonEvents
    | where Timestamp > ago(24h)
    | where AccountUpn =~ TargetUser
    | project EventTime=Timestamp,
              SourceTable="IdentityLogonEvents",
              EventType=ActionType,
              Detail=Protocol,
              IPAddress;
let AuditEvents =
    AuditLogs
    | where TimeGenerated > ago(24h)
    | where tostring(InitiatedBy) contains TargetUser
          or tostring(TargetResources) contains TargetUser
    | project EventTime=TimeGenerated,
              SourceTable="AuditLogs",
              EventType=OperationName,
              Detail=ActivityDisplayName,
              IPAddress="";
let CloudEvents =
    CloudAppEvents
    | where Timestamp > ago(24h)
    | where AccountId =~ TargetUser
          or AccountDisplayName =~ TargetUser
    | project EventTime=Timestamp,
              SourceTable="CloudAppEvents",
              EventType=ActionType,
              Detail=Application,
              IPAddress;
union isfuzzy=true SignIns, IdentityEvents, AuditEvents, CloudEvents
| order by EventTime asc

Read evidence before writing the story

First read timestamp, source, event, detail and infrastructure. Only then write the interpretation. This reduces the chance of forcing telemetry to fit a theory.

Keep contradictory evidence

If an event supports a legitimate explanation, keep it. Threat hunting should try to disprove the compromise hypothesis as seriously as it tries to prove it.

Stage 6 — test infrastructure correlation

Summarize the timeline by IP address and determine which infrastructure appears across multiple phases.

06-test-infrastructure-correlation.kql
12345678910111213141516171819202122232425262728293031323334353637383940414243
let TargetUser = "alex.wilson@contoso.com";
let Timeline =
    union isfuzzy=true
        (
            SigninLogs
            | where TimeGenerated > ago(24h)
            | where UserPrincipalName =~ TargetUser
            | project EventTime=TimeGenerated,
                      SourceTable="SigninLogs",
                      EventType="Sign-in",
                      Detail=AppDisplayName,
                      IPAddress
        ),
        (
            AuditLogs
            | where TimeGenerated > ago(24h)
            | where tostring(InitiatedBy) contains TargetUser
                  or tostring(TargetResources) contains TargetUser
            | project EventTime=TimeGenerated,
                      SourceTable="AuditLogs",
                      EventType=OperationName,
                      Detail=ActivityDisplayName,
                      IPAddress=""
        ),
        (
            CloudAppEvents
            | where Timestamp > ago(24h)
            | where AccountId =~ TargetUser
                  or AccountDisplayName =~ TargetUser
            | project EventTime=Timestamp,
                      SourceTable="CloudAppEvents",
                      EventType=ActionType,
                      Detail=Application,
                      IPAddress
        );
Timeline
| summarize EventCount=count(),
            FirstSeen=min(EventTime),
            LastSeen=max(EventTime),
            Sources=make_set(SourceTable, 10),
            EventTypes=make_set(EventType, 30)
          by IPAddress
| order by FirstSeen asc

Now make the assessment

The conclusion should come from the combined evidence: authentication sequence, source behaviour, identity changes, cloud activity, chronology and infrastructure correlation.

Match confidence to evidence

Use terms such as observed, consistent with, likely and confirmed carefully. Do not make the conclusion more certain than the telemetry permits.

Your evidence board

EvidenceAssessmentWeight
Failures before successConsistent with attempted credential access.Supporting
Same source touches several identitiesConsistent with broader credential testing if shared infrastructure is excluded.Supporting
Successful authentication from the sourceEstablishes successful access from that source.Strong
Privilege/directory activity shortly afterwardsMay indicate capability increase or persistence depending on the operation.Strong when actor and target corroborate
Post-authentication cloud actionsEstablishes activity after access and helps determine impact.Strong
Infrastructure repeated across phasesConnects otherwise separate telemetry.Supporting, subject to network context

Agent Foskett's final case timeline

01:42 — authentication failure ↓ 01:48 — authentication failure ↓ 01:53 — SUCCESS ↓ SOURCE PIVOT The IP touched multiple identities ↓ 02:07 — privilege-related activity ↓ 02:16 — directory change ↓ 02:21 — cloud activity ↓ MULTI-TABLE CORRELATION Identity, timestamps and infrastructure align ↓ ASSESSMENT Evidence is consistent with likely identity compromise followed by post-authentication activity ↓ NEXT Contain the identity Revoke active sessions Review persistence changes Determine affected resources Preserve the evidence
The final answer did not come from one clever query. It came from asking the next correct question every time the evidence changed.

Write the conclusion like an investigator

Example: The investigation identified repeated failed authentication attempts followed by a successful sign-in to the target identity from the same source. The source was also associated with authentication activity against additional identities. Privilege-related and directory activity occurred shortly after successful access, followed by cloud application activity. Taken together, the sequence is consistent with likely identity compromise and subsequent post-authentication activity. Individual privilege, persistence and impact events should be validated against their initiating actor, target resource and expected administrative activity before final incident classification.

Module 11 investigation checklist

  • Start with the identity, not the alert title.
  • Review successful and failed authentication together.
  • Establish the user's normal sign-in baseline.
  • Investigate MFA and authentication-method changes.
  • Interpret Conditional Access in context.
  • Pivot on IP addresses and other infrastructure.
  • Investigate privileged role activity.
  • Look beyond authentication into session behaviour.
  • Follow the identity across multiple tables.
  • Build a chronological evidence timeline.
  • Separate observations from conclusions.
  • Try to disprove your own hypothesis.
  • Document exactly what the evidence supports.

Lesson 140 key takeaways

  • Identity threat hunting is a process of progressive pivots.
  • No single authentication result should end an investigation prematurely.
  • The user, source IP, privilege event and session can each become the next investigative entity.
  • Authentication evidence becomes stronger when correlated with subsequent behaviour.
  • Use multiple telemetry sources when one table cannot answer the whole question.
  • Chronology is one of an analyst's strongest correlation tools.
  • Preserve contradictory evidence and legitimate explanations.
  • Match confidence to the strength of the telemetry.
  • Every important conclusion should be traceable to evidence.
  • The goal is not to prove the alert correct. The goal is to determine what happened.

Module 11 complete — Identity Threat Hunting

You began this module by investigating a successful sign-in that did not look normal. You can now hunt MFA fatigue, authentication-method registration, Conditional Access context, privileged activation, multi-account source activity, abnormal sessions, cross-table identity evidence and full compromise timelines.

Module 11 complete. You are no longer querying identity logs one event at a time — you are investigating identities as evidence.

Continue your KQL investigation training

You have completed Module 11: Identity Threat Hunting. Return to the KQL Academy to review the learning path and prepare for the next investigation module.

Related Agent Foskett Investigations

Continue applying the investigation mindset to cases where authentication, session and timeline evidence must be connected.

Complete an identity threat hunting investigation with KQL

Lesson 140 of the Agent Foskett KQL Academy completes Module 11 with an end-to-end Microsoft identity investigation using SigninLogs, AuditLogs, IdentityLogonEvents and CloudAppEvents.

Microsoft Entra and Defender XDR identity threat hunting

The investigation follows authentication failures, successful access, source-IP activity, privilege and directory events, post-authentication cloud behaviour and multi-table correlation to demonstrate how analysts can build a defensible identity compromise assessment from Microsoft security telemetry.

/div>