Il protocollo Kerberos costituisce il pilastro dell’autenticazione nelle infrastrutture Microsoft Active Directory. Progettato dal MIT negli anni ’80 e successivamente integrato nei sistemi Windows a partire da Windows 2000, Kerberos offre un meccanismo di autenticazione basato su ticket crittografici che, in teoria, elimina la necessità di trasmettere credenziali in chiaro attraverso la rete.
Tuttavia, la complessità del protocollo, unita alle scelte implementative di Microsoft e alla necessità di mantenere la retrocompatibilità con sistemi legacy, ha generato nel corso degli anni una serie di vulnerabilità strutturali e di configurazione sfruttate attivamente.
Architettura Kerberos in Active Directory
Kerberos opera attraverso tre componenti fondamentali che interagiscono tramite un sistema di ticket crittografici firmati da una Trusted Authority centrale
- Key Distribution Center (KDC): risiede sul Domain Controller e include due sottoservizi: l’Authentication Service (AS) e il Ticket Granting Service (TGS)
- Client: l’entità che richiede l’accesso a una risorsa (utente, computer, servizio)
- Application Server: la risorsa a cui si vuole accedere (file server, web application, database, ecc.)
Il flusso di autenticazione si articola in quattro messaggi principali
- AS-REQ: il client richiede un Ticket Granting Ticket (TGT) al KDC
- AS-REP: il KDC risponde con il TGT cifrato con la password hash dell’utente
- TGS-REQ: il client presenta il TGT e richiede un Service Ticket per una risorsa specifica
- TGS-REP: il KDC restituisce il Service Ticket cifrato con la chiave dell’account di servizio
Ogni ticket Kerberos contiene informazioni critiche che, se esposte o manipolate, diventano vettori di attacco
- PAC (Privilege Attribute Certificate): struttura dati firmata dal KDC che contiene i SID dell’utente, i gruppi di appartenenza e i diritti di accesso. È il cuore della privilege escalation via Golden/Silver Ticket
- Encryption Type: il tipo di cifratura negoziato tra client e KDC. Le encryption type obsolete (RC4/NTLM, DES) sono direttamente sfruttabili per attacchi offline
- Timestamp e validità: il TGT ha tipicamente una validità di 10 ore, rinnovabile fino a 7 giorni. I Service Ticket durano invece 10 ore
L’implementazione Microsoft di Kerberos introduce alcune specificità rispetto alla specifica RFC 4120 che hanno rilevanza diretta per la sicurezza
- Uso di NTLM hash come chiave crittografica: la password dell’utente viene trasformata in un hash MD4 (NTLM) usato come chiave simmetrica per cifrare le credenziali. Questo significa che chiunque ottenga l’NTLM hash può impersonare l’utente senza conoscere la password in chiaro
- PAC validation opzionale: per ragioni di performance, la validazione del PAC da parte dell’Application Server è configurabile e storicamente disabilitata in alcuni scenari, aprendo la porta al Silver Ticket
- Supporto legacy per RC4 (NTLM): mantenuto per compatibilità, ma crittograficamente debole e sfruttabile per attacchi di tipo AS-REP Roasting e Kerberoasting
Kerberoasting: Attaccare gli Account di Servizio
Il Kerberoasting sfrutta una caratteristica legittima del protocollo Kerberos: qualsiasi utente autenticato nel dominio può richiedere un Service Ticket per qualsiasi Service Principal Name (SPN) registrato. Il Service Ticket viene cifrato con la chiave derivata dalla password dell’account associato all’SPN. L’attaccante richiede Service Ticket per tutti gli SPN del dominio, estrae le informazioni dai ticket e le sottopone a cracking offline con strumenti come Hashcat o John the Ripper, senza generare traffico verso l’account target né produrre lockout. Il rischio è direttamente proporzionale alla debolezza delle password degli account di servizio.
Quindi, il primo passo è censire tutti gli account con SPN registrati, distinguendo quelli associati a utenti (i più vulnerabili) da quelli associati a computer account (meno critici)
# Ricerca di tutti gli account con SPN registrati nel dominio
Import-Module ActiveDirectory
# Account UTENTE con SPN
Get-ADUser -Filter {ServicePrincipalName -ne '$null'} `
-Properties ServicePrincipalName, PasswordLastSet, `
PasswordNeverExpires, Enabled, LastLogonDate |
Select-Object SamAccountName, Enabled, PasswordLastSet, `
PasswordNeverExpires, ServicePrincipalName |
Sort-Object PasswordLastSet |
Format-Table -AutoSize
# Esporta i risultati in un file CSV
Get-ADUser -Filter {ServicePrincipalName -ne '$null'} `
-Properties ServicePrincipalName, PasswordLastSet, PasswordNeverExpires `
| Export-Csv -Path 'C:\Audit\spn_accounts.csv' -NoTypeInformationTramite il seguente script, possiamo valutare il rischio in base al tipo di cifratura supportato dall’account. Gli account configurati per supportare RC4 (etype 23) sono significativamente più vulnerabili rispetto a quelli che supportano esclusivamente AES-256
# Verifica encryption type supportati dagli account con SPN
# msDS-SupportedEncryptionTypes: 0x18 = AES128+AES256, 0x17 = RC4+3DES+DES
Get-ADUser -Filter {ServicePrincipalName -ne '$null'} `
-Properties ServicePrincipalName, 'msDS-SupportedEncryptionTypes' |
ForEach-Object {
$encType = $_.'msDS-SupportedEncryptionTypes'
$risk = if ($encType -eq 0 -or $encType -band 0x04) { 'HIGH - RC4 abilitato' }
elseif ($encType -band 0x18) { 'LOW - Solo AES' }
else { 'MEDIUM - Da verificare' }
[PSCustomObject]@{
Account = $_.SamAccountName
SPN = $_.ServicePrincipalName -join '; '
EncType = $encType
RiskLevel = $risk
}
} | Sort-Object RiskLevel | Format-Table -AutoSizeDi seguito alcuni suggerimenti su come mitigare il rischio di questo tipo di attacco
- Managed Service Accounts (gMSA): utilizzare Group Managed Service Accounts per tutti i servizi compatibili. Le gMSA hanno password di 240 caratteri casuali, gestite automaticamente dal dominio, che rendono il cracking computazionalmente impossibile
- Password robuste: per gli account di servizio che non possono usare gMSA, imporre password di almeno 25 caratteri con alta complessità e rotazione periodica (massimo 6 mesi)
- Limitare l’uso di RC4: applicare la policy per forzare AES-256 sugli account di servizio tramite l’attributo msDS-SupportedEncryptionTypes
- Audit degli SPN orfani: rimuovere immediatamente gli SPN registrati su account inattivi o non necessari
Il seguente comando forza AES-256 su tutti gli account con SPN
Get-ADUser -Filter {ServicePrincipalName -ne '$null'} | ForEach-Object {
Set-ADUser $_ -KerberosEncryptionType AES256
Write-Host "Aggiornato: $($_.SamAccountName)" -ForegroundColor Green
}andando a mitigare il rischi di Kerberoasting RC4.
AS-REP Roasting: Utenti senza Pre-autenticazione
Il flag DONT_REQ_PREAUTH in Active Directory disabilita il requisito di pre-autenticazione Kerberos per un account utente. Quando questo flag è attivo, il KDC risponde a qualsiasi richiesta AS-REQ, anche non autenticata, con un AS-REP contenente informazioni crittografate con l’NTLM hash della password utente.
A differenza del Kerberoasting, l’AS-REP Roasting non richiede all’attaccante di essere già autenticato nel dominio: l’attacco può essere condotto da qualsiasi macchina con visibilità sulla porta 88/TCP del Domain Controller.
Vediamo come trovare tutti gli utenti con pre-autenticazione Kerberos disabilitata
Import-Module ActiveDirectory
$DONT_REQ_PREAUTH = 0x400000
Get-ADUser -Filter * -Properties UserAccountControl, PasswordLastSet, `
LastLogonDate, MemberOf |
Where-Object { $_.UserAccountControl -band $DONT_REQ_PREAUTH } |
Select-Object SamAccountName, Enabled, PasswordLastSet, LastLogonDate |
Format-Table -AutoSizeLa mitigazione è molto semplice: riabilitare la pre-autenticazione Kerberos su tutti gli account che non hanno una necessità tecnica di averla disabilitata
$DONT_REQ_PREAUTH = 0x400000
$accountsDaSistemare = Get-ADUser -Filter * -Properties UserAccountControl |
Where-Object { $_.UserAccountControl -band $DONT_REQ_PREAUTH }
foreach ($account in $accountsDaSistemare) {
try {
Set-ADAccountControl $account -DoesNotRequirePreAuth $false
Write-Host "[OK] Pre-auth riabilitata: $($account.SamAccountName)" `
-ForegroundColor Green
} catch {
Write-Host "[ERR] Fallito su $($account.SamAccountName): $_" `
-ForegroundColor Red
}
}Pass-the-Ticket: riutilizzo dei Ticket Kerberos
Il Pass-the-Ticket (PtT) sfrutta la natura dei ticket Kerberos come credenziali bearer: chiunque possieda un ticket valido, TGT o Service Ticket, può utilizzarlo per autenticarsi senza conoscere la password o l’hash dell’account. I ticket vengono estratti dalla memoria del processo LSASS (Local Security Authority Subsystem Service) su sistemi Windows compromessi.
L’attacco è particolarmente efficace in ambienti dove gli amministratori di dominio effettuano logon interattivi su workstation o server non dedicati: i loro TGT rimangono in memoria fino alla scadenza e possono essere estratti.
Vediamo come monitorare le sessioni Kerberos attive
query sessionvisualizza la lista delle sessioni di logon attive sul sistema
klistè uno strumento integrato nei sistemi Windows che consente di visualizzare e gestire i ticket Kerberos memorizzati nella cache locale.
Per il monitoraggio centralizzato a livello di dominio, è essenziale raccogliere e analizzare gli Event ID specifici di Kerberos dai Domain Controller
$domainControllers = (Get-ADDomainController -Filter *).HostName
$startTime = (Get-Date).AddHours(-24)
# Event ID rilevanti:
# 4768 - AS-REQ (richiesta TGT) - baseline per anomalie
# 4769 - TGS-REQ (richiesta Service Ticket) - kerberoasting genera burst
# 4771 - Kerberos pre-auth fallita
foreach ($dc in $domainControllers) {
Write-Host "`n=== $dc ==="
Get-WinEvent -ComputerName $dc -FilterHashtable @{
LogName = 'Security'
Id = @(4768, 4769, 4771)
StartTime = $startTime
} -MaxEvents 500 -ErrorAction SilentlyContinue |
Where-Object { $_.Message -match 'RC4' -or
$_.Message -match '0x17' } |
Select-Object TimeCreated, Id, Message |
Format-Table -Wrap -AutoSize
}Golden Ticket
Il Golden Ticket è probabilmente l’attacco Kerberos più pericoloso: consiste nella creazione di un TGT firmato con la chiave del krbtgt account, l’account interno del servizio Ticket Granting. Chiunque conosca l’NTLM hash (o la chiave AES) di krbtgt può generare ticket per qualsiasi utente, con qualsiasi SID, con qualsiasi durata, senza interagire con il Domain Controller.
Per ottenere la chiave krbtgt, un attaccante deve prima raggiungere il privilegio di Domain Admin o equivalente, tipicamente attraverso una catena di escalation che include le tecniche precedentemente descritte.
Il rilevamento del Golden Ticket è tecnicamente complesso perché il ticket è crittograficamente valido. Tuttavia esistono indicatori comportamentali e strutturali che possono essere monitorati
Import-Module ActiveDirectory
$domainControllers = (Get-ADDomainController -Filter *).HostName
# Indicatori di Golden Ticket:
# 1. Ticket con durata superiore ai 10 ore di policy (MaxTicketAge)
# 2. Account che autenticano con SID non corrispondenti all'AD
# 3. Ticket per account disabilitati o inesistenti
# 4. Autenticazione senza precedente AS-REQ (Event 4768)
$policy = Get-ADDefaultDomainPasswordPolicy
Write-Host "MaxTicketAge policy: $($policy.MaxTicketAge)"
# Cerca autenticazioni TGS (4769) senza TGT precedente (4768)
# nelle ultime 4 ore - potenziale indicatore di ticket importato
$window = (Get-Date).AddHours(-4)
foreach ($dc in $domainControllers) {
$tgtEvents = Get-WinEvent -ComputerName $dc -FilterHashtable @{
LogName='Security'; Id=4768; StartTime=$window
} -EA SilentlyContinue | ForEach-Object {
[xml]$xml = $_.ToXml()
$xml.Event.EventData.Data |
Where-Object {$_.Name -eq 'TargetUserName'} |
Select-Object -ExpandProperty '#text'
}
Get-WinEvent -ComputerName $dc -FilterHashtable @{
LogName='Security'; Id=4769; StartTime=$window
} -EA SilentlyContinue | ForEach-Object {
[xml]$xml = $_.ToXml()
$user = $xml.Event.EventData.Data |
Where-Object {$_.Name -eq 'TargetUserName'} |
Select-Object -ExpandProperty '#text'
if ($user -and $user -notin $tgtEvents) {
Write-Host "[ANOMALIA] TGS senza TGT per utente: $user su $dc" `
-ForegroundColor Yellow
}
}
}In caso di sospetta compromissione del krbtgt, o come misura preventiva dopo un incidente di sicurezza significativo, è necessario ruotare la password del krbtgt due volte, a distanza di almeno 10 ore (la validità massima dei TGT), per invalidare tutti i ticket esistenti
Import-Module ActiveDirectory
# FASE 1: Reset iniziale della password krbtgt
$krbtgt = Get-ADUser -Identity 'krbtgt'
Write-Host "Account KRBTGT: $($krbtgt.DistinguishedName)"
# Genera una nuova password casuale di 64 caratteri
$newPassword = [System.Web.Security.Membership]::GeneratePassword(64, 20)
$securePass = ConvertTo-SecureString $newPassword -AsPlainText -Force
Set-ADAccountPassword -Identity 'krbtgt' -NewPassword $securePass -Reset
Write-Host "[$(Get-Date)] Prima rotazione krbtgt completata." -ForegroundColor Yellow
Write-Host "Attendere 10+ ore prima della seconda rotazione."
# === ATTESA: almeno 10 ore ===
# FASE 2: Seconda rotazione (dopo 10+ ore)
$newPassword2 = [System.Web.Security.Membership]::GeneratePassword(64, 20)
$securePass2 = ConvertTo-SecureString $newPassword2 -AsPlainText -Force
Set-ADAccountPassword -Identity 'krbtgt' -NewPassword $securePass2 -Reset
Write-Host "[$(Get-Date)] Seconda rotazione krbtgt completata." -ForegroundColor Green
Write-Host "Tutti i Golden Ticket esistenti sono ora invalidati."Silver Ticket
Il Silver Ticket è un Service Ticket costruito con la chiave dell’account di servizio specifico, non del krbtgt. Mentre il Golden Ticket richiede la compromissione del domain controller, il Silver Ticket può essere creato dopo aver ottenuto la chiave di un singolo account di servizio.
Il Silver Ticket non richiede comunicazione con il KDC durante il suo utilizzo, poiché viene presentato direttamente all’Application Server. Questo significa che gli event log del Domain Controller non mostrano alcuna richiesta TGS per quel servizio. Lo svantaggio per l’attaccante è lo scope limitato: il Silver Ticket vale solo per il servizio specifico.
# Focus su CIFS, HOST, HTTP, MSSQL - servizi ad alto impatto
$highRiskSPNs = @('cifs/', 'host/', 'http/', 'MSSQLSvc/', 'ldap/')
Get-ADComputer -Filter * -Properties ServicePrincipalName |
Where-Object { $_.ServicePrincipalName } |
ForEach-Object {
foreach ($spn in $_.ServicePrincipalName) {
$isHighRisk = $highRiskSPNs |
Where-Object { $spn -like "$_*" }
if ($isHighRisk) {
[PSCustomObject]@{
Computer = $_.Name
SPN = $spn
RiskType = 'Silver Ticket Target'
}
}
}
} | Format-Table -AutoSize
# Rilevamento: Event 4624 con Logon Type 3
$events = Get-WinEvent -FilterHashtable @{
LogName='Security'; Id=4624; StartTime=(Get-Date).AddHours(-1)
} -MaxEvents 1000 -EA SilentlyContinue |
Where-Object { $_.Message -match 'Logon Type:\s+3' -and
$_.Message -match 'AuthenticationPackageName:\s+Kerberos' }
Write-Host "Autenticazioni Kerberos di rete nell'ultima ora: $($events.Count)"La mitigazione più efficace contro il Silver Ticket è abilitare la validazione del PAC (Privilege Attribute Certificate) lato server. Quando la PAC validation è attiva, l’Application Server contatta il KDC per verificare la firma del PAC prima di concedere l’accesso, rendendo inutilizzabile qualsiasi Silver Ticket il cui PAC non sia stato firmato dal KDC reale.
$servers = Get-ADComputer -Filter {OperatingSystem -like '*Server*'} |
Select-Object -ExpandProperty Name
foreach ($server in $servers) {
try {
$val = Invoke-Command -ComputerName $server -ScriptBlock {
Get-ItemProperty `
'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters' `
-Name ValidateKdcPacSignature -EA SilentlyContinue
}
$status = if ($val.ValidateKdcPacSignature -eq 1) { 'OK' } else { 'DA CONFIGURARE' }
$color = if ($status -eq 'OK') { 'Green' } else { 'Red' }
Write-Host "$server : PAC Validation = $status" -ForegroundColor $color
} catch {
Write-Host "$server : IRRAGGIUNGIBILE" -ForegroundColor DarkGray
}
}Possiamo effettuare questa impostazione tramite
- registry: in HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters creando la chiave ValidateKdcPacSignature > REG_DWORD > 1
- GPO: Computer Configuration > Administrative Templates > System > Kerberos > ‘Require strict KDC validation’
Delega Kerberos
La delega Kerberos permette a un servizio di impersonare un utente per accedere ad altri servizi in suo nome. Esistono tre modalità, con profili di rischio molto diversi
| Tipo | Descrizione | Rischio |
|---|---|---|
| Unconstrained Delegation | Il servizio riceve una copia del TGT dell’utente e può usarlo per qualsiasi risorsa nel dominio | Critico |
| Constrained Delegation (KCD) | Il servizio può impersonare l’utente solo verso servizi specifici elencati in msDS-AllowedToDelegateTo | Alto |
| Resource-Based Constrained Delegation (RBCD) | Il controllo è nell’account di destinazione via msDS-AllowedToActOnBehalfOfOtherIdentity | Medio |
L’Unconstrained Delegation è equivalente a dare al servizio le credenziali complete dell’utente: qualsiasi compromissione del sistema delegante espone potenzialmente tutti gli utenti che vi si autenticano.
Con il seguente script PowerShell è possibile fare un audit delle deleghe Kerberos
Import-Module ActiveDirectory
Write-Host "`n=== UNCONSTRAINED DELEGATION (CRITICO) ==="
# TrustedForDelegation = $true indica Unconstrained Delegation
# I Domain Controller hanno Unconstrained per design
Get-ADComputer -Filter { TrustedForDelegation -eq $true } `
-Properties TrustedForDelegation, OperatingSystem |
Where-Object { $_.Name -notlike '*DC*' } |
Select-Object Name, OperatingSystem |
Format-Table -AutoSize
Get-ADUser -Filter { TrustedForDelegation -eq $true } `
-Properties TrustedForDelegation |
Select-Object SamAccountName, DistinguishedName |
Format-Table -AutoSize
Write-Host "`n=== CONSTRAINED DELEGATION ==="
Get-ADObject -Filter { msDS-AllowedToDelegateTo -like '*' } `
-Properties 'msDS-AllowedToDelegateTo', SamAccountName |
Select-Object SamAccountName, 'msDS-AllowedToDelegateTo' |
Format-Table -Wrap -AutoSize
Write-Host "`n=== RESOURCE-BASED CONSTRAINED DELEGATION ==="
Get-ADObject -Filter { 'msDS-AllowedToActOnBehalfOfOtherIdentity' -like '*' } `
-Properties 'msDS-AllowedToActOnBehalfOfOtherIdentity' |
Select-Object Name, DistinguishedName |
Format-Table -AutoSizeUna delle catene di attacco più note che sfrutta la Unconstrained Delegation è il famoso Printer Bug scoperto nel 2018: un attaccante posizionato su un sistema con Unconstrained Delegation può indurre il Domain Controller ad autenticarsi verso di esso tramite il servizio Print Spooler, ottenendo così il TGT del computer account del Domain Controller.
Monitoring
Un programma di monitoraggio efficace richiede la definizione di una baseline degli eventi Kerberos per poter rilevare le anomalie. La tabella seguente riepiloga gli Event ID critici da abilitare e monitorare sui Domain Controller
| Event ID | Evento | Rilevanza per la sicurezza |
|---|---|---|
| 4768 | AS-REQ (TGT Request) | Baseline autenticazioni. Burst anomali o richieste con etype RC4 (0x17) indicano AS-REP Roasting |
| 4769 | TGS-REQ (Service Ticket) | Burst su account multipli in breve tempo: Kerberoasting. EncryptionType RC4 su account che dovrebbero usare AES |
| 4770 | TGT Renewal | Rinnovi frequenti da IP inusuali possono indicare movimento laterale con ticket rubati |
| 4771 | Pre-auth Failure | Tentativi ripetuti: password spray. Fallimenti su account non esistenti |
| 4776 | NTLM Auth (DC) | NTLM in ambienti Kerberos-only è anomalo |
| 4624 (Type 3) | Network Logon | Logon Kerberos di rete senza 4768/4769 correlato: potenziale Silver Ticket o Pass-the-Ticket |
