Yuval Gordon Ricercatore di sicurezza | Microsoft

Questo articolo presenta un nuovo attacco che colpisce i Group Managed Service Accounts (gMSA), soprannominato attacco "Golden GMSA", che consente agli aggressori di scaricare gli attributi della chiave root del Key Distribution Service (KDS) e quindi di generare la password per tutti i gMSA associati offline.

TL;DR

Un attaccante con privilegi elevati può ottenere in qualsiasi momento tutti gli ingredienti per generare la password di qualsiasi gMSA nel dominio con due passaggi:

  1. Recuperare diversi attributi dalla chiave radice KDS nel dominio
  2. Utilizzare il GoldenGMSA per generare la password di qualsiasi gMSA associato alla chiave, senza un account privilegiato.

Lettura correlata

gMSA 101

In genere le password degli account di servizio non vengono ruotate regolarmente, mettendole a rischio, soprattutto perché possono essere prese di mira tramite Kerberoasting attacchi. A gMSA (group Managed Service Account; la g minuscola è un mistero) è un tipo speciale di account in Active Directory (AD) introdotto in Windows Server 2012 per risolvere proprio questo problema. L'unico scopo di questo oggetto è quello di essere utilizzato come account di servizio, con l'importante caratteristica della rotazione delle password. Un account gMSA può essere utilizzato da uno o più server con servizi compatibili.

La password della gMSA è gestita da AD. Viene ruotata automaticamente ogni 30 giorni su una password generata in modo casuale di 256 byte, rendendola impossibile da decifrare. Come documentazione Microsoft descrive:

Descrizione di Microsoft Key Distribution Service da MS Docs

La password viene calcolata in base a un segreto che cambia periodicamente e ad attributi non nominati del gMSA. Il segreto utilizzato è memorizzato nell'oggetto chiave principale del KDS.

Rotazione automatica della password: com'è possibile?

L'idea alla base di questo tipo di account è interessante. I DC scrivibili gestiscono la password del gMSA e la ruotano ogni 30 giorni (per impostazione predefinita). Quando un server che utilizza questo account ha bisogno di utilizzare il gMSA, richiede innanzitutto la password più recente al DC recuperando un attributo chiamato msDS-Password gestita. Questo attributo è un BLOB (Binary Large Object) che contiene la password.

L'attributo msDS-GroupMSAMembership di un gMSA specifica chi è autorizzato a ottenere la password. Il DC scrivibile, a sua volta, utilizza questo attributo per convalidare che il chiamante sia autorizzato a ottenerla. Fin qui, possiamo vedere un modo semplice per abusarne: Se un utente malintenzionato accede a un account che ha accesso a msDS-ManagedPassword, può leggere la password per il gMSA specifico.

Memorizzazione della password

Di solito i DC non memorizzano le password nei loro database, ma solo i segreti derivati dalle password. Ciò solleva una domanda: Supponiamo che il DC scrivibile non memorizzi la password in chiaro; come è possibile recuperarla leggendo l'attributo msDS-ManagedPassword? Si scopre che msDS-ManagedPassword è un attributo attributo costruitocioè non è memorizzato nell'AD, ma viene calcolato quando un utente autorizzato tenta di leggerlo.

Come viene costruita la msDS-ManagedPassword?

Ora sappiamo che la password viene costruita su richiesta dai DC scrivibili. Sappiamo anche che ogni DC scrivibile può costruire l'attributo e il risultato sarà sempre lo stesso. Questa pagina mostra come viene generata la password, ma non è abbastanza dettagliata da permetterci di costruirla da soli.

La ricerca della funzione che costruisce questo attributo ci porterebbe a ntdsai.dll!dbGetConstructedAtt, che è la funzione responsabile della costruzione degli attributi.

dbGetManagedServiceAccountPassword

Possiamo vedere una chiamata a dbGetManagedServiceAccountPasswordma siamo siamo interessati solo a la password piuttosto che l'intero ManagedPasswordBlob. Scavando ulteriormente nella la funzione alla fine ci porta a a a chiamata alla alla funzione KdsCli.dll!KdsGetGmsaPasswordBasedOnKeyId.

KdsGetGmsaPasswordBasedOnKeyId

Esaminiamo i parametri di questa funzione:

  • _SecurityDescriptor è un descrittore di sicurezza (SD) predefinito, codificato in ntdsai.dll, che concede autorizzazioni di lettura e scrittura a S-1-5-9 (controller di dominio aziendali), come mostrato nella seguente schermata:
gmsaSecurityDescriptor
  • _SID è l'ObjectSID della gMSA desiderata.
  • _MsdsManagedPasswordID è un attributo dell'oggetto gMSA che, tra le altre cose, fa riferimento tramite GUID all'istanza della chiave radice KDS utilizzata da gMSA per la generazione della password.
    Non abbiamo trovato una documentazione formale per questo attributo, ma ulteriori ricerche ci hanno aiutato a capire come costruirlo da soli con i parametri mostrati nella schermata seguente.
Msds_ManagedpasswordID
  • _OutPassword è un puntatore a un buffer che memorizzerà la password.
  • La dimensione della password è il numero di byte che verranno scritti in OutPassword. Il valore predefinito è 256.

Recupero della chiave e costruzione della password

Il flusso di esecuzione arriva infine alla funzione GetKeyFromKdsService, che invoca il metodo RPC GetKey.

getKeyStatus

Si può notare che i parametri corrispondono alla documentazione di [MS-GKDI]

Metodo GetKey

Nota interessante: GetKey esegue controlli di accesso rispetto al TargetSD fornito dal chiamante, il che significa che possiamo invocare questa funzione con un descrittore di sicurezza che ci garantisce l'accesso e il DC restituirà una chiave. Purtroppo, la SD viene utilizzata anche per il calcolo della chiave. Quindi, anche se possiamo sempre cambiare la SD per aggirare i controlli di accesso, a meno che la SD fornita non sia valida, otterremo una chiave non valida. L'unico descrittore di sicurezza valido che dà luogo a una chiave valida è quello codificato in modo rigido di cui abbiamo parlato prima (gmsaSecurityDescriptor), che garantisce l'accesso solo ai controller di dominio aziendali (S-1-5-9).

Se il chiamante dispone dei permessi richiesti, questo metodo genera una chiave e la restituisce in una struttura Group Key Envelope (GKE). Dopo aver ottenuto la chiave, si può finalmente chiamare kdscli.dll!_GenerateGmsaPassword per generare la password.

GenerareGmsaPassword

Il sesto e il settimo parametro sono facoltativi e non influiscono sulla password. Quindi, per questo scopo, possiamo impostarli a null.

Ricostruzione della generazione di password gMSA

Una password gMSA viene generata richiamando una funzione che risiede in kdscli.dll (purtroppo non esportata), che si trova su qualsiasi endpoint Windows. La chiamata di questa funzione richiede tre cose:

  1. SID 
  2. msds-ManagedPasswordID della gMSA (può essere recuperato utilizzando una query LDAP)
  3. GKE, che può essere generato chiamando il metodo GetKey sul DC con privilegi elevati tramite RPC

Implementazione di GetKey e generazione di password offline

Abbiamo cercato di semplificare il più possibile la generazione delle password gMSA, in modo da poterla eseguire offline. L'unica chiamata RPC del processo è quella per GetKey. Abbiamo quindi deciso di invertire il processo e di portarlo in codice C# che genera una GKE.

Abbiamo scoperto che la chiave cambia periodicamente, come documentato da Microsoft. Ma la chiave è derivata dagli attributi dell'oggetto chiave principale KDS e da tre numeri interi (L0KeyID, L1KeyID, L2KeyID) derivati da un timestamp, come mostrato nella seguente schermata.

GetCurrentIntervalID

Il timestamp corrente è memorizzato nell'attributo msDS-ManagedPasswordID di gMSA, leggibile per impostazione predefinita da tutti gli utenti del dominio, in modo da poter recuperare il timestamp e generare questi numeri interi.

Gli unici ingredienti che il DC utilizza per generare le password, ma che noi non abbiamo, sono i seguenti attributi della chiave principale KDS:

  • cn
  • msKds-SecretAgreementParam
  • msKds-RootKeyData
  • msKds-KDFParam
  • msKds-KDFAlgorithmID
  • msKds-CreateTime
  • msKds-UseStartTime
  • msKds-Versione
  • msKds-DomainID
  • msKds-Lunghezza chiave privata
  • msKds-Lunghezza chiave pubblica
  • msKds-SecretAgreementAlgorithmID

Il recupero di questi attributi richiede i diritti di lettura e di estensione sull'oggetto chiave radice KDS, che solo gli amministratori di dominio hanno per impostazione predefinita. Tuttavia, questi valori NON vengono modificati periodicamente.

Ciò significa che se compromettiamo questi valori, possiamo usarli per calcolare un GKE per qualsiasi gMSA associato alla chiave radice del KDS e generare la sua password offline.

L'attacco della GMSA d'oro 

L'attacco Golden GMSA si verifica quando un aggressore scarica gli attributi rilevanti di una chiave radice KDS e li utilizza per generare la password degli account gMSA associati offline. L'attacco Golden GMSA è in qualche modo simile all'attacco Golden Ticket, che consente agli aggressori che compromettono l'account krbtgt di falsificare i Ticket Granting Ticket (TGT) finché la password krbtgt rimane invariata.

Una differenza notevole tra l'attacco Golden Ticket e l'attacco Golden GMSA è che non siamo a conoscenza di un modo per ruotare la chiave segreta del KDS. Pertanto, se una chiave radice KDS è compromessa, non c'è modo di proteggere i gMSA ad essa associati.. L'unica mitigazione in questo scenario è la creazione di nuovi gMSA con una nuova chiave radice KDS.

Armamento dell'attacco Golden GMSA

Abbiamo armato l'attacco Golden GMSA in uno strumento che si può scaricare qui qui.

Lo strumento GoldenGMSA Attack può recuperare gli attributi necessari da un oggetto chiave radice KDS specificato o utilizzare i valori forniti dall'utente per generare una GKE. Lo strumento può anche recuperare la msDS-ManagedPasswordID basata su un SID gMSA e, naturalmente, generare la password del gMSA offline.

Un utente malintenzionato può potenzialmente utilizzare la password per compromettere i servizi che utilizzano il gMSA falsificando un Silver Ticket o ottenendo un ticket di servizio Kerberos per gli account privilegiati tramite S4U2Self. Se il gMSA ha privilegi elevati, l'aggressore potrebbe usarlo per compromettere altre risorse e, in alcuni casi, compromettere l'intera foresta.

Esempio di attacco Golden GMSA

Un utente malintenzionato può utilizzare lo strumento GoldenGMSA per enumerare tutti i gMSA e le chiavi radice KDS ad essi associate. Un utente malintenzionato con privilegi elevati può anche utilizzare lo strumento GoldenGMSA per eseguire il dump delle chiavi radice KDS.

gMSA_Enumerate

L'attaccante può in seguito utilizzare il KDS scaricato root key BLOB per generare la password della gMSA completamente offline.

gMSA_Compute

La password è codificata Base64 perché potrebbe includere caratteri non stampabili.

Rilevamento di un attacco Golden GMSA

Evento 4662 è stata eseguita un'operazione su un oggetto

Il compromesso di un KDS root knon genera eventi di sicurezza per impostazione predefinita. I difensori dovrebbero configurare un SACL sul il KDS root koggetti per tutti coloro che leggono tutti coloro che leggono il msKds-RootKeyData attributo. Una volta l'attributo di controllo dell'accesso al sistema (SACL) è configurato, qualsiasitentativo di scaricare i dati chiave di un KDS root kgenererà un evento di sicurezza evento di sicurezza 4662 sul DC dove il tipo di oggetto è msKds-ProvRootKey e il nome del conto non è un DCcome dimostra la seguente schermata:

Difesa dagli attacchi Golden GMSA

I Group Managed Service Accounts sono un'ottima funzionalità di Active Directory che mitiga alcuni rischi associati agli account di servizio, come gli attacchi Kerberoasting. Tuttavia, le password associate ai gMSA sono generate utilizzando input che non possono essere ruotati se compromessi, consentendo agli aggressori con privilegi elevati di scaricare le chiavi di root KDS e generare le password dei gMSA associati offline per tutto il tempo in cui esistono.

I difensori devono monitorare gli accessi anomali alle chiavi root KDS, come la lettura dell'attributo msKds-ProvRootKey da parte di non DC e gli eventi di accesso anomali legati agli account gMSA.