Chapter 35

Cross-Host Log Correlation

A single host's logs tell one part of the story. Correlating logs across multiple hosts — the domain controller, the compromised workstation, the file server, and the firewall — reveals the complete attack chain. This chapter covers building multi-host timelines, resolving time skew, and pivoting between log sources.

Scenario

An attacker used a compromised workstation (WS01) to access a file server (FS01) and a domain controller (DC01) using stolen credentials. WS01's logs were partially cleared. But: DC01 has authentication logs (4624/4648 with logon type and source), FS01 has file access logs (4663), and the firewall has connection logs for external traffic. Correlating these three sources fills the gaps that WS01's cleared logs left. The DC logs show when the stolen credentials were used; FS01 logs show what was accessed; the firewall logs show where the data went.

Building a Multi-Host Correlated Timeline

  Cross-Host Log Correlation Framework
  ═══════════════════════════════════════════════════════════════════

  Step 1: Collect logs from all relevant hosts
    ├── SIEM (if available): pull all logs for the time window
    ├── Evtx files: \\host\c$\Windows\System32\winevt\Logs\
    ├── Firewall: syslog export from NGFW/proxy
    ├── DC: Security.evtx (authentication events)
    └── File servers: Security.evtx (object access events if auditing enabled)

  Step 2: Normalize to UTC
    ├── Confirm all host clocks are UTC or note timezone offsets
    ├── Document any NTP desync (check System.evtx for time-sync events)
    └── Apply offsets: log_UTC = log_local + offset

  Step 3: Build a unified timeline
    ├── Tag each event with source host
    ├── Sort all events chronologically
    └── Look for event chains across hosts within expected latency windows

  Event chain example:
    02:13:05 UTC  WS01  4688: powershell.exe spawned (cmd: IEX download)
    02:13:07 UTC  FW    Outbound HTTPS to 185.220.101.47 (WS01 src IP)
    02:13:12 UTC  DC01  4624: jsmith logged in from WS01 (type 3 network)
    02:13:15 UTC  FS01  4663: jsmith accessed \\FS01\Finance\Q3-Revenue.xlsx
    02:14:02 UTC  FW    7.3 MB upload to 185.220.101.47 (WS01 src IP)

  Reading: malware download → C2 checkin → lateral to FS01 → exfil in 57 seconds
Why cross-host correlation beats single-host analysis

Attackers expect you to look at the compromised host. That's where they focus their log-clearing effort. The DC, file server, and firewall are out of the attacker's direct control and are frequently untouched. A cleared Security.evtx on WS01 means nothing if DC01's 4624 log still records every session WS01 initiated, and FS01's 4663 log still records every file jsmith touched. Cross-host correlation makes log clearing largely futile — you reconstruct the attacker's actions from the hosts they couldn't reach.

Correlation Scripts

PowerShellmulti-host-correlation.ps1
# Collect and correlate authentication events across multiple hosts
# Run from a host with network access to target systems

$HOSTS = @("DC01", "FS01", "EXCHANGE01")
$StartTime = [DateTime]::Parse("2026-09-17T02:00:00Z")
$EndTime   = [DateTime]::Parse("2026-09-17T06:00:00Z")
$SuspectUser = "jsmith"

$allEvents = [System.Collections.Generic.List[PSObject]]::new()

foreach ($host in $HOSTS) {
    Write-Host "Collecting from $host..."
    $events = Invoke-Command -ComputerName $host -ScriptBlock {
        param($start, $end, $user)
        Get-WinEvent -FilterHashtable @{
            LogName   = "Security"
            Id        = @(4624, 4648, 4625, 4663, 4688)
            StartTime = $start
            EndTime   = $end
        } -ErrorAction SilentlyContinue |
        Where-Object {
            $_.Message -match $user -or $_.Id -in @(4688)
        } |
        Select-Object TimeCreated, Id, Message,
            @{N="HostName"; E={$env:COMPUTERNAME}}
    } -ArgumentList $StartTime, $EndTime, $SuspectUser

    if ($events) { $events | ForEach-Object { $allEvents.Add($_) } }
}

# Sort by time and export
$allEvents |
    Sort-Object TimeCreated |
    Select-Object TimeCreated, HostName, Id,
        @{N="Summary"; E={ $_.Message -split "`n" | Select-Object -First 3 | Join-String -Separator " | " }} |
    Export-Csv "D:\analysis\correlated-timeline.csv" -NoTypeInformation

Write-Host "Total events correlated: $($allEvents.Count)"
Common mistake: correlating by username instead of logon session ID

When you filter event logs by username (e.g., "jsmith"), you catch every event tied to that account — including legitimate pre-attack activity that pollutes your timeline with noise. Prefer correlating by Logon ID (field 0x3e7, 0x3e5, or a specific hex value that appears in both the 4624 and the 4688/4663 events). The Logon ID ties a specific authenticated session to all process creations and file accesses within it, giving you a clean sub-timeline of just the attacker's session — not every historical action by that user account.

Key Pivot Techniques

Starting artifactPivot toWhat you learn
4624 logon from WS01 to DC01 with jsmithWS01 Security.evtx for 4648 (explicit credential use) at same timeWhich process on WS01 initiated the DC authentication — confirms malware using stolen credentials
4663 file access on FS014624 on FS01 immediately preceding the accessThe logon session the file access happened under — confirms how attacker authenticated to FS01
Firewall log: WS01 outbound upload to external IPWS01 process creation logs (4688) in same time windowWhich process made the outbound connection — the exfiltration tool
DC01 4768/4769 (Kerberoasting): service ticket requests for many SPNs in rapid successionWS01 logs for the source of those requests (same IP/session)Confirms Kerberoasting happened from WS01; correlate with any offline cracking indicators

Pre-Incident Log Retention Requirements

Cross-host correlation is only possible if the logs still exist. Configure these before the incident:

Log sourceMinimum retentionWhat breaks if it rolls over
DC Security.evtx90 days, ≥1 GB log sizeAuthentication history gone — impossible to map credential use back to initial compromise date
File server Security.evtx (4663)30 days, ≥512 MBCan't prove which files were accessed — data scope assessment fails
Windows Security on all endpoints30 days, ≥256 MBProcess creation (4688) history lost — attacker tool execution unrecoverable
Firewall/proxy logs90 daysC2 channel start date unknown — dwell time calculation fails; exfiltration volume lost
SIEM (forwarded)365 days minimum for regulated industriesFallback when local logs roll; also the only source if local logs are cleared

Q & A

Q: Host clocks across the environment are off by different amounts. How much does time skew matter?

It depends on the skew and the question you're asking. If you're building a 47-day investigation timeline, a 5-minute clock skew barely matters — events hours or days apart are clearly sequential. But if you're trying to determine whether a process was created before or after a network connection on the same host within a 10-second window, a 5-minute skew makes that analysis impossible. Check: (1) Each host's System event log for Event ID 1 (time adjustment) or check w32tm /query /status remotely. (2) Compare the timestamps of the same repeatable event across hosts (e.g., a scheduled task that runs at a known time on all hosts). (3) Document the skew in your case notes — courts and stakeholders want to know that you've accounted for it. For high-precision correlation (<1 minute windows), note the estimated skew in your report and flag any conclusions within the skew window as uncertain. SIEM platforms usually address this via NTP normalization, but host-collected evtx files retain the local clock timestamp.