Yuval Gordon Ricercatore di sicurezza | Microsoft

I sistemi di identità, in particolare Active Directory, che è il principale archivio di identità per la maggior parte delle aziende, sono costantemente sotto attacco da parte dei criminali informatici perché rappresentano la porta d'accesso ai sistemi informativi critici di un'organizzazione, compresi i preziosi dati dei clienti.

In questa sede esploreremo una tattica poco conosciuta della Discretionary Access Control List (DACL) che gli aggressori possono utilizzare per nascondere l'appartenenza a un gruppo ed eventualmente eludere il rilevamento. Utilizzando l'attributo Primary Group ID e una specifica Access Control Entry (ACE), è possibile nascondere l'appartenenza a un gruppo di cui si è già membri, senza avere alcun permesso sul gruppo. Questo trucco non può funzionare con i membri di gruppi protetti come gli amministratori di dominio, ma può funzionare con i membri di gruppi normali come DnsAdmins, che possono essere usati per passare ad amministratori di dominio.

Lettura correlata

Come Active Directory gestisce la normale appartenenza ai gruppi

Per comprendere appieno l'aggiunta di questa tecnica, è necessario avere una conoscenza di base del modo in cui le appartenenze ai gruppi sono gestite da Active Directory. Ogni controller di dominio memorizza un database di Active Directory (ntds.dit). All'interno di ogni ntds.dit c'è una colonna chiamata DNT (Distinguished Name Tag), che è come l'ID dell'oggetto nel database. Quando si aggiunge un utente a un gruppo, il controller di dominio aggiunge una riga a una tabella chiamata "link_table" che salva un collegamento tra il DNT del membro (backlink_DNT) e il DNT del gruppo (link_DNT).

Fin qui è abbastanza semplice, ma l'appartenenza a un gruppo non è solo questo. Esiste un altro attributo chiamato PrimaryGroupID (PGID) che specifica il Relative Identifier (RID) del gruppo primario dell'utente, che è l'ultima parte del SID principale (SID principale = SID di dominio + RID). Per impostazione predefinita, questo attributo è impostato su 513 (Utenti di dominio) per i nuovi utenti, 515 (Computer di dominio) per i nuovi computer, 516 (Controllori di dominio) per i controllori di dominio e 521 per i controllori di dominio di sola lettura. Questo attributo può essere impostato anche facendo clic sul pulsante "Imposta gruppo primario" nella scheda "Membri di" all'interno dello strumento Utenti e computer di Active Directory, se l'accesso in scrittura richiesto è presente sull'utente di destinazione.

Impostazione del gruppo primario in Active Directory
Impostazione del gruppo primario

Utilizzando questo strumento, è possibile impostare il gruppo primario solo su un gruppo di cui l'utente è già membro. La particolarità di questo attributo, e il motivo per cui gli amministratori di Active Directory dovrebbero conoscerlo per evitare abusi da parte di avversari, è che impostando l'ID gruppo primario (PGID), si disattiva il collegamento di appartenenza tra il gruppo e il membro. In altre parole, il collegamento viene rimosso dalla suddetta tabella link_table.

"Ma come è possibile, Yuval? Quando eseguo una query per i membri del gruppo Domain Admins, vedo anche utenti che hanno il gruppo primario impostato su domain admins!". Ottima domanda, lettore!

La maggior parte degli strumenti che interrogano i membri chiede in realtà due cose. Immaginiamo di voler ottenere tutti i membri del gruppo Domain Admins:

  1. Lo strumento interrogherà l'attributo member, che farà sì che il DC controlli la tabella link_table e restituisca gli oggetti che hanno un link member con il gruppo Domain Admins.
  2. Lo strumento cercherà qualsiasi oggetto che abbia un valore di 512 (RID degli amministratori di dominio) nell'attributo PrimaryGroupID.

Perché è necessario monitorare l'uso dell'ID primario di gruppo

Utilizzando l'ID primario del gruppo, si fa in modo che l'appartenenza a uno dei gruppi sia scritta all'interno di un attributo sul lato membro. Per capire meglio cosa si può ottenere con questa azione, analizziamola dal punto di vista di un attaccante.

Immaginate di voler nascondere l'appartenenza di un utente a uno dei suoi gruppi. Con l'appartenenza normale, si potrebbe semplicemente specificare una voce di controllo dell'accesso (ACE) di Active Directory per negare l'accesso a tutti su "leggi l'appartenenza al gruppo". Tuttavia, questo approccio renderà l'appartenenza dell'utente quasi vuota (il gruppo principale sarà ancora visualizzato), il che potrebbe sembrare sospetto. Inoltre, con questo approccio si nasconde l'appartenenza solo dal lato del membro e non dal lato del gruppo. Quindi, se qualcuno cerca di leggere uno dei membri del gruppo, l'utente sarà ancora elencato.

È qui che entra in gioco il PGID: Specificando il gruppo primario, è possibile rendere l'appartenenza elencata solo dal lato dei membri. Se si aggiunge un ACE per negare a tutti la lettura del PGID sull'oggetto, una delle appartenenze al gruppo è ora nascosta, sia dal lato dei membri che da quello dei gruppi.

Come gli aggressori possono utilizzare l'ID primario del gruppo per nascondere gli utenti malintenzionati

Utilizzando una semplice funzione di PowerShell, è possibile nascondere l'utente "haxer" dal gruppo "attackers", cambiando il PGID con il RID del gruppo "attackers" e aggiungendo un deny-read sul PGID.

Adesione dal lato dell'utente
Adesione dal lato dell'utente

The primary group now shows <None>. Odd, but still might go unnoticed.

Appartenenza ad Active Directory dal lato del gruppo
Adesione dal lato del gruppo

Il codice seguente può essere utilizzato per nascondere l'appartenenza a un gruppo specifico di cui l'utente è già membro, se l'utente in esecuzione ha la DACL di scrittura (modifica dei permessi) sull'utente di destinazione. Per esempio, per nascondere me stesso (haxer) dal gruppo degli attaccanti di cui sono già membro (RID 2607), ho usato la funzione mostrata sopra. Ho impostato il flag "AddWritePGIDToCurrent" su true perché non avevo i permessi richiesti: avevo solo il permesso WriteDACL.

function Hide-Membership {
  param (
    [parameter(Mandatory = $true)]
    [string]$TargetDN,
             
    [parameter(Mandatory = $true)]
    [int]$RID,

    [parameter(Mandatory = $false)]
    [bool]$AddWritePGIDToCurrent = $false
  )

  $target = [ADSI]"LDAP://$TargetDN"
  $identityReference = (New-Object System.Security.Principal.NTAccount("everyone")).Translate([System.Security.Principal.SecurityIdentifier])
  $guid = New-Object Guid "bf967a00-0de6-11d0-a285-00aa003049e2" # Guid of primaryGroupID attribute

  $target.PsBase.Options.SecurityMasks = "Dacl"

  if ($AddWritePGIDToCurrent) {
    $identityReferenceCurrentUser = ([System.Security.Principal.WindowsIdentity]::GetCurrent()).User
    $aceAllow = New-Object System.DirectoryServices.ActiveDirectoryAccessRule @($identityReferenceCurrentUser,"WriteProperty","Allow",$Guid)
    $target.PsBase.ObjectSecurity.AddAccessRule($aceAllow)
    $target.CommitChanges()
  }

  $aceDeny = New-Object System.DirectoryServices.ActiveDirectoryAccessRule @($identityReference,"ReadProperty","Deny",$Guid)

  $target.PsBase.ObjectSecurity.AddAccessRule($aceDeny)
  $target.CommitChanges()
  $target.primarygroupid = $RID 
  $target.CommitChanges()
}
Hide-Membership -TargetDN "CN=haxer,CN=Users,DC=f047-d01,DC=lab" -RID 2607 -AddWritePGIDToCurrent $true

Si noti che questa tecnica non funzionerà sui membri di un gruppo protetto dal processo SDPROP e da AdminSDHolder, poiché ci si affida alla DACL, che in tal caso verrà semplicemente riportata alla DACL di AdminSDHolder ogni ora circa.

Rilevamento dell'uso dannoso dell'ID del gruppo primario per nascondere l'appartenenza al gruppo.

È possibile rilevare l'uso di PGID per nascondere l'appartenenza monitorando gli ACE impostati su deny on read per questa proprietà. Ma questo può essere un compito difficile senza gli strumenti o i sistemi adeguati.

Un'opzione è quella di usare periodicamente la seguente riga di comando per cercare qualsiasi utente con un PGID che non si riesce a leggere. Non sono a conoscenza di alcuna ragione legittima per cui un utente abbia un PGID inesistente o illeggibile, ma potrebbe accadere, per cui si potrebbero vedere dei falsi positivi.

Get-ADUser -Filtro {-not(primaryGroupID -like "*")}

Un modo più semplice per monitorare l'uso dannoso di questa tecnica: Semperis Directory Services Protector include un indicatore che monitora e avvisa gli utenti con la configurazione "Utenti e computer senza PGID leggibile".

Proteggere Active Directory dalla continua ondata di attacchi può essere impegnativo. Tuttavia, monitorando costantemente l'ambiente per individuare i molti modi in cui gli aggressori possono sfruttare determinate configurazioni, è possibile identificare e porre rimedio alle intrusioni prima che diventino violazioni su larga scala.