🏢Active DirectoryAccountsPermissionsPrivileged Access

Spoofing di primaryGroupID: i Domain Admins Nascosti che gli Audit di Active Directory Non Rilevano

Impostare primaryGroupID a 512 rende un account un Domain Admin a pieno titolo senza toccare l'attributo member del gruppo — invisibile per la maggior parte degli export di audit.

Younes AZABARDi Younes AZABAR11 min di lettura
Spoofing di primaryGroupID: i Domain Admins Nascosti che gli Audit di Active Directory Non Rilevano

Impostate l'attributo primaryGroupID di un account utente a 512 e diventa membro a pieno titolo di Domain Admins a ogni accesso. Questo è lo spoofing di primaryGroupID: Domain Admins nascosti che Active Directory calcola direttamente nel token Kerberos dell'account, ma che ADSI Edit, un filtro LDAP grezzo (member=...), e la maggior parte degli export di audit non vedono mai — perché solo metà del modo in cui AD calcola l'appartenenza ai gruppi è effettivamente memorizzata sull'oggetto gruppo.

Cos'è primaryGroupID

Ogni oggetto utente e computer di Active Directory porta un attributo primaryGroupID: un singolo intero che memorizza il Relative Identifier (RID) del gruppo primario dell'account. È un residuo dei requisiti di conformità POSIX di Windows NT, di prima che AD supportasse i gruppi annidati arbitrari, e oggi resta perlopiù intatto al suo valore predefinito — al punto che un recente thread r/activedirectory chiedeva semplicemente a cosa serva realmente il campo "Primary Group" di un oggetto utente.

I valori predefiniti, confermati dalla documentazione di audit degli eventi di Microsoft e dalla ricerca di Semperis su questo attributo:

Tipo di oggettoprimaryGroupID predefinitoNome del gruppo
Utente513Domain Users
Computer515Domain Computers
Domain Controller516Domain Controllers
DC di sola lettura521Read-only Domain Controllers

Quello che conta per questo articolo: il RID 512 è Domain Admins.

A differenza dell'appartenenza ordinaria a un gruppo — che risiede nell'attributo multivalore member dell'oggetto gruppo, con un corrispondente collegamento inverso memberOf sull'utente — l'appartenenza al gruppo primario è memorizzata solo sull'account, come un singolo intero. L'oggetto gruppo stesso non registra nulla al riguardo.

Come Active Directory Calcola Realmente "Chi È in Questo Gruppo"

"Chi è in Domain Admins" non è una singola query. L'appartenenza effettiva è l'unione di due elementi distinti:

  1. Ogni account elencato nell'attributo member del gruppo Domain Admins.
  2. Ogni account il cui attributo primaryGroupID è uguale a 512 — il RID di Domain Admins — indipendentemente da ciò che dice l'attributo member.

Solo la prima metà è memorizzata sull'oggetto gruppo. La seconda metà è memorizzata interamente sull'account, e nulla sul gruppo registra che questo collegamento esista. Gli strumenti che risolvono l'appartenenza interrogando direttamente l'oggetto gruppo ricostruiscono entrambe le metà e mostrano il quadro completo. Gli strumenti che si limitano a leggere il valore grezzo member del gruppo vedono solo la prima metà.

La ricerca di TrustedSec su questo comportamento (Brandon Colley, pubblicata a gennaio 2026) dimostra direttamente questa scissione: interrogare Get-ADGroupMember "Domain Admins" sul gruppo restituisce un account il cui accesso a Domain Admins proviene esclusivamente da primaryGroupID — il cmdlet risolve l'unione. Active Directory Users and Computers e Active Directory Administrative Center fanno lo stesso quando si apre la scheda Membri del gruppo. Ma la stessa ricerca mostra che due strumenti si trovano sull'altro lato della scissione:

  • ADSI Edit, esaminando direttamente l'attributo member, non elenca l'account.
  • Un filtro LDAP grezzo come (member=CN=...) — il tipo su cui si basano la maggior parte degli script di export fatti in casa, dei lavori di reporting basati su CSV, e delle pipeline di ingestione SIEM — lo manca per lo stesso motivo: sta interrogando l'attributo che non è mai stato toccato.

C'è una seconda lacuna, più ristretta, nella stessa ricerca: Get-ADGroupMember -Recursive attraversa i gruppi annidati per espandere l'appartenenza, ma non rileva un account il cui gruppo primario è impostato su un gruppo annidato dentro Domain Admins anziché Domain Admins stesso. La ricorsione espande la catena member; non riesegue l'unione di primaryGroupID a ogni livello di annidamento — lo stesso punto cieco transitivo trattato in l'annidamento pericoloso di gruppi.

Spoofing di primaryGroupID: i Domain Admins Nascosti che Active Directory Non Elenca Mai

Un attaccante (o uno script) con accesso in scrittura all'attributo primaryGroupID di un utente target — un diritto GenericWrite, GenericAll, o un WriteProperty con ambito delegato da qualche parte in fondo a una OU, la stessa classe di arco di abuso ACL che BloodHound mappa già sugli oggetti utente — lo imposta a 512. Active Directory accetta questa scrittura solo su un account che è già membro esplicito del gruppo target — le indicazioni di Microsoft sull'impostazione programmatica del gruppo primario e la ricerca di Tenable su questo attributo confermano entrambe che un semplice Set-ADUser -Replace @{primaryGroupID=512} fallisce contro un account che non è già membro, e che solo un bypass del servizio di directory come DCShadow può impostarlo su un account che non è mai stato membro affatto. Il percorso ordinario è di tre comandi, non uno:

Add-ADGroupMember -Identity "Domain Admins" -Members jdoe
Set-ADUser -Identity jdoe -Replace @{primaryGroupID=512}
Remove-ADGroupMember -Identity "Domain Admins" -Members jdoe -Confirm:$false

Alla successiva richiesta di TGT Kerberos dell'account, il RID del gruppo primario viene incorporato nel token esattamente come qualsiasi altro SID di gruppo. L'account ora si autentica con accesso equivalente a Domain Admins. Una volta completato il terzo comando, l'attributo member di Domain Admins torna al suo elenco originale, cosicché un diff pianificato degli export di gruppo o una lettura statica dell'attributo member non ha più nulla da rilevare dopo il fatto — sebbene la breve aggiunta e rimozione generino ciascuna un evento standard di cambio di appartenenza al gruppo lungo il percorso, quindi un avviso in tempo reale su quegli eventi specifici (a differenza di un diff di export periodico) ha davvero una finestra per rilevarlo. Ecco perché questa tecnica si legge come uno spoofing di primaryGroupID: Domain Admins nascosti che Active Directory stesso incorpora in ogni token, ma che il controllo costruito per rilevare i nuovi admin non vede mai.

Il ricercatore di sicurezza Yuval Gordon documenta, in un post sul blog di Semperis, un'ulteriore estensione di questa idea: abbinare la modifica di primaryGroupID a un Access Control Entry di negazione della lettura sull'attributo primaryGroupID dell'utente stesso, in modo che anche gli strumenti consapevoli dell'unione (ADUC, Get-ADGroupMember) non possano più leggere il valore e smettano del tutto di segnalare l'appartenenza. È una tecnica reale — ma Gordon è esplicito su dove smette di funzionare:

"Questo trucco non può funzionare sui membri di gruppi protetti come Domain Admins... questa tecnica non funzionerà sui membri di alcun gruppo protetto dal processo SDPROP e da AdminSDHolder, poiché ci basiamo sulla DACL, che in quel caso verrà semplicemente ripristinata alla DACL di AdminSDHolder circa ogni ora."

Il ciclo SDProp di AdminSDHolder (circa ogni 60 minuti) riapplica una ACL modello a qualsiasi account consideri membro di un gruppo protetto, il che cancella l'ACE di negazione. Poiché una semplice modifica di primaryGroupID=512 non tocca affatto la DACL dell'account, SDProp non la ripristina — sventa solo il trucco di occultamento tramite ACE di negazione, non lo spoofing sottostante. L'esempio funzionante dello stesso Gordon punta invece a un gruppo di test non protetto, non a DnsAdmins — lo stesso post nota separatamente che la tecnica funziona anche contro gruppi ordinari come DnsAdmins, che ha un proprio percorso ben noto verso Domain Admins. La versione semplice — impostare primaryGroupID direttamente a 512, senza l'ACE — non è comunque influenzata da AdminSDHolder, il che è esattamente il motivo per cui vale la pena verificarla direttamente.

Rilevamento

Questo è un caso in cui il monitoraggio degli Event ID di Windows gioca davvero a vostro favore. Il riferimento di audit di sicurezza di Microsoft per l'Event ID 4738 ("Un account utente è stato modificato", nella sottocategoria Audit User Account Management) documenta un campo Primary Group ID nei dati degli attributi modificati dell'evento, e la sua stessa tabella di raccomandazioni di monitoraggio lo afferma chiaramente:

Campo da monitorareMotivo del monitoraggio
Primary Group ID diverso da 513Normalmente, il valore di Primary Group è 513 per gli utenti di dominio e locali. Altri valori devono essere monitorati.

Due controlli indipendenti, corrispondenti alle due cose che è realmente necessario rilevare:

Tempo Reale — Verificare la Modifica Stessa

Con Audit User Account Management abilitato, ogni scrittura di primaryGroupID genera l'Event ID 4738 sul DC che l'ha elaborata, con il nuovo RID nel campo Primary Group ID. Impostate un avviso su qualsiasi 4738 in cui quel campo è valorizzato e il nuovo valore non è 513 (o 515/516/521 per computer e DC).

Istantanea nel Tempo — Scansione degli Account Già Spoofati

La ricerca di TrustedSec fornisce un comando diretto per questo:

Get-ADUser -property primaryGroup,primaryGroupID -Filter {-not(primaryGroupID -like "513")}

Eseguito contro un dominio con una baseline pulita, gli unici risultati attesi sono i domain controller (516), gli RODC (521), e — se il vostro ambiente ne effettua ancora il provisioning — account di servizio mappati POSIX con una motivazione documentata. Qualsiasi account utente ordinario che mostra 512, o qualsiasi RID privilegiato che non dovrebbe avere, costituisce il rilievo.

Nessuno dei due controlli dipende dalla lettura dell'oggetto gruppo Domain Admins — ed è proprio questo il punto. Una revisione basata su Get-ADGroupMember "Domain Admins" eseguita direttamente contro il gruppo lo rileverebbe anch'essa, secondo la stessa ricerca; una revisione basata su un export LDAP dell'attributo member, o uno strumento che tratta quell'export come verità assoluta, non lo farà.

Rimedio

  1. Eseguite la scansione sopra su ogni dominio della foresta, non solo su quello che ospita Domain Admins — l'abuso di primaryGroupID contro un gruppo annidato/locale in un dominio figlio è altrettanto invisibile per gli export dell'attributo member.
  2. Ripristinate ogni account non conforme al suo valore predefinito corretto (513 per gli utenti standard) a meno che non esista una motivazione di business documentata e attuale per un valore diverso.
  3. Abilitate Audit User Account Management su tutti i domain controller se non è già attivo, così che l'Event ID 4738 venga effettivamente generato e inoltrato al vostro SIEM.
  4. Ricostruite qualsiasi revisione automatizzata degli accessi privilegiati che interroga member direttamente — tramite ADSI Edit, un filtro LDAP grezzo (member=...), o uno script di export costruito allo stesso modo — perché invochi invece Get-ADGroupMember sul gruppo, o unisca esplicitamente una scansione primaryGroupID. La revisione che doveva essere la rete di sicurezza è precisamente il controllo che questa tecnica sventa.
  5. Verificate chi detiene WriteProperty/GenericWrite/GenericAll sugli oggetti utente, e chi può aggiungere membri a Domain Admins direttamente — il percorso ordinario verso questa tecnica richiede entrambi: il diritto di aggiungere brevemente l'account target a Domain Admins, e il diritto di scrivere il suo primaryGroupID. Uno qualsiasi dei due delegato al di sotto delle OU di amministrazione integrate è di per sé un rilievo.

Come EtcSec Rileva Questo

Il controllo PRIMARYGROUPID_SPOOFING di EtcSec esegue la stessa classe di scansione come controllo continuo: ogni audit confronta il primaryGroupID di ogni account con il suo valore predefinito atteso e segnala gli account il cui gruppo primario differisce senza una motivazione documentata, colmando esattamente la lacuna che un export limitato all'attributo member lascia aperta. I rilievi emergono accanto alla revisione dei permessi di scrittura (ACL_WRITE_PROPERTY_EXTENDED) che mostra chi poteva effettuare la modifica in primo luogo, e accanto al monitoraggio dei gruppi privilegiati (PRIVILEGED_GROUP_MEMBER_CHANGES) così potete vedere, fianco a fianco, quali percorsi di escalation dei privilegi il vostro alerting sull'attributo member copre realmente.

Esplora le pagine di identity security collegate a questo tema