When a security alert appears, a clear sequence matters more than speed alone. This playbook gives a practical step-by-step workflow you can run in authorized environments using native Windows + PowerShell.

Step 1: Confirm authentication anomalies

Start by checking failed logons, lockouts, and successful logons in the same period.

# Failed logons
Get-WinEvent -FilterHashtable @{
  LogName='Security'
  Id=4625
  StartTime=(Get-Date).AddHours(-2)
} | Select-Object TimeCreated, Id, Message -First 200
# Lockouts
Get-WinEvent -FilterHashtable @{
  LogName='Security'
  Id=4740
  StartTime=(Get-Date).AddHours(-2)
} | Select-Object TimeCreated, Id, Message
# Successful logons
Get-WinEvent -FilterHashtable @{
  LogName='Security'
  Id=4624
  StartTime=(Get-Date).AddHours(-2)
} | Select-Object TimeCreated, Id, Message -First 200

What to check: repeated source hosts, failed-to-successful patterns, unusual account usage.

Step 2: Validate account and privilege changes

Check whether users/groups changed around the same time as the alert.

# User account created
Get-WinEvent -FilterHashtable @{ LogName='Security'; Id=4720; StartTime=(Get-Date).AddDays(-1) } |
Select-Object TimeCreated, Id, Message
# User account deleted
Get-WinEvent -FilterHashtable @{ LogName='Security'; Id=4726; StartTime=(Get-Date).AddDays(-1) } |
Select-Object TimeCreated, Id, Message
# Group membership changes
Get-WinEvent -FilterHashtable @{ LogName='Security'; Id=4732; StartTime=(Get-Date).AddDays(-1) } |
Select-Object TimeCreated, Id, Message
Get-WinEvent -FilterHashtable @{ LogName='Security'; Id=4733; StartTime=(Get-Date).AddDays(-1) } |
Select-Object TimeCreated, Id, Message

Step 3: Inspect process execution

Find suspicious process launches and high-resource processes.

# Process creation events
Get-WinEvent -FilterHashtable @{
  LogName='Security'
  Id=4688
  StartTime=(Get-Date).AddHours(-2)
} | Select-Object TimeCreated, Id, Message -First 200
# Current high CPU processes
Get-Process | Sort-Object CPU -Descending |
Select-Object -First 25 Name, Id, CPU, Path

What to check: executables launched from temp/user-writable locations, unknown binaries, unusual parent-child process behavior.

Step 4: Check persistence indicators

# New service installed
Get-WinEvent -FilterHashtable @{
  LogName='System'
  Id=7045
  StartTime=(Get-Date).AddDays(-1)
} | Select-Object TimeCreated, Id, Message

If available in your environment, also review scheduled tasks and startup changes.

Step 5: Build a network activity snapshot

# Active established sessions
Get-NetTCPConnection -State Established |
Select-Object LocalAddress, LocalPort, RemoteAddress, RemotePort, OwningProcess
# Map process IDs
Get-Process | Select-Object Id, Name, Path

What to check: unusual outbound destinations, uncommon remote ports, repeated connections from unexpected processes.

Step 6: Verify log integrity and endpoint detections

# Security log cleared
Get-WinEvent -FilterHashtable @{
  LogName='Security'
  Id=1102
  StartTime=(Get-Date).AddDays(-2)
} | Select-Object TimeCreated, Id, Message
# Defender malware detections
Get-WinEvent -FilterHashtable @{
  LogName='Microsoft-Windows-Windows Defender/Operational'
  Id=1116
  StartTime=(Get-Date).AddDays(-7)
} | Select-Object TimeCreated, Id, Message

Step 7: Export evidence immediately

$Out = "C:\Temp\triage_$(Get-Date -Format yyyyMMdd_HHmmss)"
New-Item -Path $Out -ItemType Directory -Force | Out-Null

Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625; StartTime=(Get-Date).AddHours(-6)} |
  Select TimeCreated, Id, Message |
  Export-Csv "$Out\failed_logons.csv" -NoTypeInformation

Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4740; StartTime=(Get-Date).AddHours(-6)} |
  Select TimeCreated, Id, Message |
  Export-Csv "$Out\lockouts.csv" -NoTypeInformation

Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4688; StartTime=(Get-Date).AddHours(-6)} |
  Select TimeCreated, Id, Message |
  Export-Csv "$Out\process_create_4688.csv" -NoTypeInformation

Get-NetTCPConnection -State Established |
  Select LocalAddress, LocalPort, RemoteAddress, RemotePort, OwningProcess |
  Export-Csv "$Out\net_connections.csv" -NoTypeInformation

Get-Process |
  Select Name, Id, CPU, Path |
  Export-Csv "$Out\process_list.csv" -NoTypeInformation

Step 8: Write a concise incident summary

  • Trigger and detection source
  • Top indicators observed
  • Affected users/systems
  • Containment actions completed
  • Next action and owner

This sequence keeps triage consistent, evidence-focused, and easier to hand off across teams.

By Nizar