Understanding lastLogon vs. lastLogonTimestamp in Active Directory: Which One Reveals True User Activity?


1 views

html

In Active Directory (AD), both lastLogon and lastLogonTimestamp track authentication events, but with critical technical differences:

  • lastLogon:
    • Precise real-time recording of every successful authentication
    • Not replicated between domain controllers (DC-specific)
    • Stored as 64-bit integer representing FILETIME (100-nanosecond intervals since 1601)
  • lastLogonTimestamp:
    • Replicated across domain controllers with loose consistency
    • Updates only when the time difference exceeds 14 days (by default)
    • Optimized for cross-DC queries at the expense of precision

For forensic investigations like your terminated employee case:

# PowerShell script to compare both attributes across all DCs
Import-Module ActiveDirectory

$username = "jdoe"
$cutoffDate = [datetime]"2023-10-15"

# Query all DCs for lastLogon (requires admin rights)
$lastLogons = Get-ADDomainController -Filter * | ForEach-Object {
    $dc = $_.HostName
    Get-ADUser $username -Properties lastLogon -Server $dc | 
    Select-Object @{Name='DC';Expression={$dc}},
                  @{Name='lastLogon';Expression={[datetime]::FromFileTime($_.lastLogon)}}
}

# Get the replicated timestamp
$llt = Get-ADUser $username -Properties lastLogonTimestamp |
       Select-Object @{Name='lastLogonTimestamp';Expression={[datetime]::FromFileTime($_.lastLogonTimestamp)}}

# Display results
$lastLogons | Sort-Object lastLogon -Descending
$llt

Consider these scenarios:

Situation lastLogon lastLogonTimestamp
Daily workstation login Updates every time Only updates after 14+ days
Terminated employee Shows true last access May show cached value
Multi-DC environment Different per DC Synchronized eventually

For maximum accuracy:

  1. Query lastLogon from all domain controllers
  2. Check the Security event logs (Event ID 4624) on DCs
  3. Examine workstation logs if the user had a dedicated machine
  4. Review VPN authentication logs if remote access was enabled

When monitoring account activity:

# Scheduled task to track true last logons
$scriptBlock = {
    $users = Get-ADUser -Filter * -Properties lastLogon
    $report = foreach ($u in $users) {
        [PSCustomObject]@{
            SamAccountName = $u.SamAccountName
            LastLogonUTC = if ($u.lastLogon) { [datetime]::FromFileTime($u.lastLogon) } else { $null }
            DC = $env:COMPUTERNAME
            Timestamp = Get-Date
        }
    }
    $report | Export-Csv -Path "C:\ADAudit\lastLogons_$(Get-Date -Format yyyyMMdd).csv" -Append
}

# Run on each DC via scheduled task
Register-ScheduledJob -Name "AD LastLogon Tracker" -ScriptBlock $scriptBlock -Trigger (New-JobTrigger -Daily -At 3am)

When investigating user login activity in Active Directory, you'll encounter two similar-looking but fundamentally different attributes:

  • lastLogon: Records the exact timestamp of the most recent authentication (local to each domain controller)
  • lastLogonTimestamp: A replicated attribute with intentional latency (typically 9-14 days behind)

The scenario you described (lastLogon showing pre-termination while lastLogonTimestamp shows post-termination) occurs because:

  1. lastLogon updates in real-time but isn't replicated across DCs
  2. lastLogonTimestamp replicates across the domain but with a built-in delay to prevent replication storms

For accurate forensic investigation, you need to:

# PowerShell script to check lastLogon across all DCs
$user = "username"
$domain = "yourdomain.com"
$dcs = Get-ADDomainController -Filter * | Select-Object HostName

$lastLogons = @()
foreach ($dc in $dcs) {
    $userObj = Get-ADUser $user -Properties lastLogon -Server $dc.HostName
    $lastLogons += [PSCustomObject]@{
        DC = $dc.HostName
        LastLogon = if ($userObj.lastLogon) { [datetime]::FromFileTime($userObj.lastLogon) } else { $null }
    }
}

$lastLogons | Sort-Object LastLogon -Descending | Select-Object -First 1
Attribute Best Use Case Accuracy Window
lastLogon Real-time security investigations Precise to the second
lastLogonTimestamp Account cleanup scripts ±14 days tolerance

For routine cleanup (where exact precision isn't critical), use lastLogonTimestamp:

# Find users who haven't logged in for 90+ days
$inactiveThreshold = (Get-Date).AddDays(-90)
Get-ADUser -Filter {Enabled -eq $true} -Properties lastLogonTimestamp | 
Where-Object { $_.lastLogonTimestamp -lt $inactiveThreshold.ToFileTime() } |
Select-Object SamAccountName, @{
    Name="LastLogonDate"; 
    Expression={[datetime]::FromFileTime($_.lastLogonTimestamp)}
}
  • Neither attribute tracks interactive vs network logins specifically
  • lastLogonTimestamp may show values up to 14 days older than actual last login
  • Some authentication methods (like SSPI) may not update these attributes