Chapter 37

Active Directory Logs

The Domain Controller's Security event log is the authoritative record of all authentication events in an Active Directory environment. This chapter covers investigating Kerberos attacks (Kerberoasting, AS-REP Roasting, Pass-the-Ticket), DCSync, Golden Ticket, and persistence via AD object modification.

Scenario

An attacker compromised a workstation, escalated privileges, and then targeted Active Directory. The DC Security logs reveal the complete sequence: Event 4768 for a large number of TGT requests (AS-REP Roasting attempt), followed by Event 4769 with Encryption Type 0x17 (RC4 = Kerberoasting indicator), followed by Event 4662 (DCSync — directory service access to read all password hashes). The attacker had domain admin within 4 hours of initial access.

Kerberos Attack Detection

AttackEvent ID(s)Detection indicator
AS-REP Roasting4768 (TGT request)TGT requests for accounts with "Do not require Kerberos pre-authentication" set; Result Code 0x0 (success); RC4 encryption type for the TGT
Kerberoasting4769 (service ticket request)Service ticket request with Ticket Encryption Type 0x17 (RC4_HMAC = weak); large number of 4769 events in short window for different SPNs from same source
Pass-the-Ticket4768, 4769Valid Kerberos tickets used from an IP address that didn't originally receive them (logon hours vs ticket time); service tickets requested from different IPs than the original TGT
DCSync4662DS-Replication-Get-Changes-All (Object Type: 1131f70e-e70a-11d2) accessed by a non-DC account (should only be DC machine accounts performing replication)
Golden Ticket4768TGT with unusually long lifetime (default is 10 hours; Golden Tickets often set to 10 years); TGT for domain account from unexpected source IP or time
PowerShellkerberoasting-detection.ps1
# Detect Kerberoasting from DC Security logs
# Event 4769: Kerberos service ticket request with RC4 encryption

$StartTime = [DateTime]::Parse("2026-09-17T00:00:00Z")
$EndTime   = [DateTime]::Parse("2026-09-18T00:00:00Z")

$kerberoasting = Get-WinEvent -ComputerName "DC01" -FilterHashtable @{
    LogName   = "Security"
    Id        = 4769
    StartTime = $StartTime
    EndTime   = $EndTime
} -ErrorAction SilentlyContinue |
Where-Object {
    # Ticket Encryption Type 0x17 = RC4 (Kerberoastable)
    $_.Message -match "Ticket Encryption Type:\s+0x17"
} |
ForEach-Object {
    # Parse the event message
    $msg = $_.Message
    $serviceAccount = ($msg | Select-String "Service Name:\s+(.+)").Matches.Groups[1].Value.Trim()
    $clientIP       = ($msg | Select-String "Client Address:\s+(.+)").Matches.Groups[1].Value.Trim()
    $accountName    = ($msg | Select-String "Account Name:\s+(.+)").Matches.Groups[1].Value.Trim()

    [PSCustomObject]@{
        Time           = $_.TimeCreated
        AccountName    = $accountName
        ServiceAccount = $serviceAccount
        ClientIP       = $clientIP
        EncType        = "RC4 (0x17)"
    }
}

# Group by source IP — rapid requests from one IP = Kerberoasting tool
$kerberoasting | Group-Object ClientIP | Sort-Object Count -Descending |
    Select-Object Name, Count | Format-Table
PowerShelldcsync-detection.ps1
# Detect DCSync (credential dump via replication API)
# Event 4662 with specific GUIDs for DS-Replication-Get-Changes-All

# DCSync GUIDs (hardcoded — these don't change between AD versions):
$REPLICATION_GUID_ALL   = "1131f70e-e70a-11d2-9820-00c04f8eea45"
$REPLICATION_GUID_BASIC = "1131f70f-e70a-11d2-9820-00c04f8eea45"

$dcSync = Get-WinEvent -ComputerName "DC01" -FilterHashtable @{
    LogName = "Security"
    Id      = 4662
} -ErrorAction SilentlyContinue |
Where-Object {
    $_.Message -match $REPLICATION_GUID_ALL -or
    $_.Message -match $REPLICATION_GUID_BASIC
} |
ForEach-Object {
    $msg = $_.Message
    $account = ($msg | Select-String "Subject:.+?Account Name:\s+(.+)").Matches.Groups[1].Value.Trim()

    # Filter out DC machine accounts (legitimate replication)
    if ($account -notmatch '\$$') {    # $ suffix = machine account
        [PSCustomObject]@{
            Time    = $_.TimeCreated
            Account = $account
            Event   = "DCSync — replication rights accessed by non-DC account"
        }
    }
} | Sort-Object Time

if ($dcSync) {
    Write-Warning "DCSync detected!"
    $dcSync | Format-Table -AutoSize
} else {
    Write-Host "No DCSync detected in log range"
}

AD Persistence Investigation

PowerShellad-persistence.ps1
# Detect AD persistence mechanisms via DC audit logs

# 1. New domain admin accounts (Event 4728 = user added to security group)
Get-WinEvent -ComputerName "DC01" -FilterHashtable @{
    LogName = "Security"
    Id      = @(4728, 4732, 4756)  # Added to global/local/universal group
} | Where-Object {
    $_.Message -match "Domain Admins|Enterprise Admins|Schema Admins|Administrators"
} | Select-Object TimeCreated, Id, Message | Format-List

# 2. Golden Ticket indicators (Event 4768 with unusually long ticket lifetime)
# Requires enhanced DC Kerberos auditing
# Look for TGT RequestedTicketLifetime > 600 minutes (10 hours = default max)

# 3. New user accounts created in domain (Event 4720)
Get-WinEvent -ComputerName "DC01" -FilterHashtable @{
    LogName   = "Security"
    Id        = 4720
    StartTime = (Get-Date).AddDays(-7)
} | Select-Object TimeCreated,
    @{N="NewUser"; E={ ($_.Message | Select-String "New Account Name:\s+(.+)").Matches.Groups[1].Value }},
    @{N="CreatedBy"; E={ ($_.Message | Select-String "Subject:.+?Account Name:\s+(.+)").Matches.Groups[1].Value }} |
    Format-Table

# 4. AdminSDHolder modification (persistence via protected group abuse)
# Event 5136 (directory object modified)
Get-WinEvent -ComputerName "DC01" -FilterHashtable @{
    LogName = "Security"
    Id      = 5136
} | Where-Object {
    $_.Message -match "AdminSDHolder|CN=AdminSDHolder"
} | Select-Object TimeCreated, Message | Format-List

Q & A

Q: The DC Security logs only go back 3 days because the log size wasn't configured large enough. The attack happened 6 days ago. What's the fallback?

Several alternative sources cover the gap: (1) SIEM: if DC logs were being forwarded to a SIEM in real-time, the SIEM retains them even if the local log file rolled over. This is the primary reason for SIEM forwarding. (2) Windows Event Forwarding (WEF): many organizations forward DC security events to a central collector — check the WEF server for the rolled-over events. (3) NTDS.dit database: the AD database doesn't store event logs, but it does store the state of all objects including account creation dates, group membership history, and the exact time password hashes were last changed. An account created 6 days ago with a never-used password = attacker account. (4) NetFlow: authentication over Kerberos (port 88) is visible in NetFlow. Kerberoasting = many rapid 88/udp connections from one source. DCSync = a non-DC IP making port 389 (LDAP) or 9389 (AD web services) connections to a DC with large response sizes. (5) LDAP query logs: if LDAP auditing (Event 1644) was enabled on the DC, LDAP queries (including BloodHound-style enumeration) are logged independently from authentication events and in a different log file that may have slower rollover. (6) Backup restoration: if a DC backup exists from before the roll, you can restore it to a non-joined VM and access its Security log offline.