Agent Foskett Academy • KQL Academy • Module 11 • Lesson 139

Lesson 139 — Building an Identity Compromise Timeline

An identity compromise rarely arrives as one perfect alert.

It arrives as fragments: a failed sign-in, a successful authentication, an unfamiliar IP address, a directory change, cloud activity and perhaps a privileged action several minutes later.

The investigator's job is to stop viewing those fragments independently and determine their order. In this lesson we use KQL to reconstruct the sequence, identify the turning points and build a timeline where every conclusion can be traced back to evidence.

A timeline does not make the evidence stronger. It makes the relationship between the evidence visible.
Agent Foskett KQL Academy identity compromise timeline investigation
What you will investigate

A suspected identity compromise reconstructed from authentication, audit, identity and cloud evidence.

✓ Find the earliest suspicious event
✓ Add identity and audit changes
✓ Add post-authentication activity
✓ Build a defensible chronology

The investigation begins

01:42 Failed authentication ↓ 01:48 Another failure ↓ 01:53 Successful sign-in from the same unfamiliar source ↓ 02:02 Cloud activity begins ↓ 02:07 Privileged activity appears ↓ 02:16 A directory change is recorded ↓ Each event looks different ↓ But the timestamps tell one story ↓ QUESTION Where did the compromise begin, and what happened after access was obtained?

Learning objectives

Reconstruct a suspected identity compromise chronologically, identify the earliest relevant authentication activity, add directory and cloud evidence, combine multiple event streams and distinguish observed facts from investigative conclusions.

Why chronology matters

Sequence changes meaning. A privileged role activation followed by an unfamiliar sign-in tells a different story from an unfamiliar sign-in followed minutes later by privilege activation. The events may be identical; their order is not.

Step 1 — establish the authentication sequence

Begin with SigninLogs and include failures as well as successes. The compromise may have started before the first successful authentication.

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

Do not start at the alert time

An alert is often generated after the important activity has already begun. Search backwards far enough to capture reconnaissance, failed authentication, MFA activity or other events that may explain the later success.

Success is a turning point

Repeated failures followed by a success from the same unusual source can become a critical transition in the timeline. It still requires context, but it gives the investigator a precise point from which to examine subsequent activity.

Step 2 — understand whether the source was new

Look beyond the incident window. Summarize the user's recent source, location and application history so you can decide whether the suspicious event represents a genuine change in behaviour.

baseline-signin-history.kql
123456789
let TargetUser = "alex.wilson@contoso.com";
SigninLogs
| where TimeGenerated > ago(7d)
| where UserPrincipalName =~ TargetUser
| summarize FirstSeen=min(TimeGenerated),
            LastSeen=max(TimeGenerated),
            EventCount=count()
          by IPAddress, Location, AppDisplayName
| order by FirstSeen asc

First seen does not mean malicious

A new IP address can be caused by travel, mobile networks, home internet, VPN infrastructure or normal address changes. The value of first-seen evidence comes from combining it with timing and subsequent actions.

Baseline before conclusion

The timeline should distinguish between “new to this user” and “malicious.” One is an observation. The other is a conclusion requiring additional evidence.

Step 3 — add directory and identity changes

Search AuditLogs for operations involving the identity as an initiator or target. Authentication compromise often becomes visible through what changes after access is obtained.

add-audit-events-to-investigation.kql
12345678910111213
let TargetUser = "alex.wilson@contoso.com";
AuditLogs
| where TimeGenerated > ago(24h)
| where tostring(InitiatedBy) contains TargetUser
       or tostring(TargetResources) contains TargetUser
| project EventTime=TimeGenerated,
          SourceTable="AuditLogs",
          EventType=OperationName,
          Detail=ActivityDisplayName,
          Result,
          InitiatedBy,
          TargetResources
| order by EventTime asc

Look for persistence

Authentication-method registration, role changes, application consent, account changes and other directory operations can indicate attempts to maintain access. Their significance increases when they follow suspicious authentication closely.

Actor and target are different questions

An audit event can involve the compromised identity as the actor, the target or both. Preserve InitiatedBy and TargetResources until you understand who performed the action and what was changed.

Step 4 — add post-authentication cloud activity

Now inspect what the account did in connected cloud applications after the suspicious sign-in.

add-cloud-activity-to-timeline.kql
1234567891011121314
let TargetUser = "alex.wilson@contoso.com";
CloudAppEvents
| where Timestamp > ago(24h)
| where AccountId =~ TargetUser
       or AccountDisplayName =~ TargetUser
| project EventTime=Timestamp,
          SourceTable="CloudAppEvents",
          EventType=ActionType,
          Detail=Application,
          IPAddress,
          CountryCode,
          City,
          ObjectName
| order by EventTime asc

Actions give authentication meaning

A suspicious sign-in with no meaningful follow-on activity is one investigation. The same sign-in followed by file access, mailbox changes, sharing or administrative actions is another. Post-authentication behaviour helps establish impact.

Keep the objects where possible

Knowing that an action occurred is useful. Knowing which file, mailbox, application or object was touched can make the timeline much more defensible and help determine scope.

Step 5 — assemble the master timeline

Shape the important datasets into common columns and stack them with union. The goal is one ordered sequence rather than four separate query results.

assemble-identity-compromise-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

The timeline is an investigative model

The combined query is not claiming every event is malicious. It creates a working chronology containing the events relevant to the hypothesis. The analyst still has to classify each event.

Use consistent labels

Generic fields such as EventTime, SourceTable, EventType and Detail make the timeline readable while preserving the original source for validation.

Step 6 — identify infrastructure connecting the sequence

Summarize the timeline by IP address to see whether the same infrastructure appears at several stages of the incident.

find-infrastructure-across-timeline.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

Blank IP addresses are still evidence

Some audit events do not expose an IP address in the same way as sign-in or cloud activity. Do not discard them. Their timestamp and identity relationship may still place them precisely in the sequence.

Correlation is cumulative

No single connector needs to carry the whole case. Identity + close timing + matching IP + unusual behaviour + consequential changes can collectively support a much stronger conclusion than any one field alone.

From raw events to investigative phases

Timeline phaseTypical evidenceInvestigation question
Pre-accessFailures, unfamiliar source, MFA attempts.Was someone testing or attempting access?
Initial accessSuccessful authentication.When did access first succeed?
Post-authenticationCloud and application activity.What did the identity do after access?
PrivilegeRole activation or privileged operations.Did the actor increase capability?
PersistenceAuthentication methods, consent or account changes.Was access made easier to regain?
ImpactData access, sharing, mailbox or administrative changes.What was affected?

Separate fact from interpretation

Evidence statementInterpretation
01:53 — successful sign-in from IP X.The account authenticated successfully from that source.
IP X was not seen in the previous seven days.The source is unusual for the observed baseline.
02:07 — privileged activity occurred.Privilege-related activity followed the authentication by 14 minutes.
02:16 — authentication method changed.The sequence may be consistent with persistence, but intent requires corroboration.

Agent Foskett's investigation

01:42 Authentication failure ↓ 01:48 Authentication failure ↓ 01:53 SUCCESS New source IP ↓ 02:02 Cloud activity ↓ 02:07 Privileged activity ↓ 02:16 Directory change ↓ The events are unioned ↓ The timeline is sorted ↓ Each conclusion is tied to its source ↓ The investigation no longer says: "The account looked suspicious" ↓ It says: "Here is the sequence of evidence showing how the identity changed from attempted access to successful authentication, privileged activity and persistence."
A defensible investigation is not a confident story. It is a story whose sentences can be traced back to evidence.

Investigation questions to ask next

  • What is the earliest suspicious event in the sequence?
  • Were there failed attempts before successful authentication?
  • Was the successful source new or unusual for the user?
  • What happened in the first five, fifteen and sixty minutes after access?
  • Did the identity perform directory or privileged changes?
  • Were authentication methods, roles or application permissions modified?
  • What cloud objects or data were accessed?
  • Which events share infrastructure, identity or close timing?
  • Which statements are facts and which are interpretations?
  • Can every major conclusion be traced back to the original telemetry?

Lesson 139 key takeaways

  • Identity compromise is best understood as a sequence, not a collection of alerts.
  • Search before the alert time to find the real beginning.
  • Failed authentication can be important pre-access evidence.
  • Compare suspicious sources with the user's recent baseline.
  • Add audit and cloud activity to establish what happened after authentication.
  • Use union to assemble multiple event streams chronologically.
  • Preserve the source table so every event remains traceable.
  • Separate observed facts from investigative interpretation.
  • Use identity, time, infrastructure and behaviour as cumulative correlation signals.
  • A defensible timeline explains not only what happened, but the order in which it happened.

Continue your KQL investigation training

Lesson 139 brings the Module 11 evidence together. One lesson remains: a complete identity threat-hunting investigation that requires you to apply the module from first clue to final conclusion.

Related Agent Foskett Investigations

Continue with investigations where chronology turns disconnected security events into a coherent evidence chain.

🔎 KQL Academy — Module 11: Identity Threat Hunting

Use KQL to investigate identity behaviour as evidence.

Build an identity compromise timeline with KQL

Lesson 139 of the Agent Foskett KQL Academy teaches analysts how to reconstruct a Microsoft identity compromise chronologically using SigninLogs, AuditLogs, IdentityLogonEvents and CloudAppEvents.

Microsoft Entra identity compromise investigation timeline

By combining authentication, directory, identity and cloud evidence, analysts can identify the earliest suspicious event, establish initial access, track post-authentication activity and create a defensible sequence where each conclusion remains traceable to its original telemetry.