Charlie Clark

Lavorando con i ticket Kerberos ho scoperto che potevo autenticarmi ad altri domini all'interno di una foresta Active Directory (AD) attraverso trust esterni non transitivi. Ciò significa che non esiste un "trust non transitivo". Il termine è nel migliore dei casi fuorviante e offre agli amministratori di sistema un falso senso di sicurezza. In questo post vedremo, tra le altre cose, come gli aggressori possono autenticarsi ad altri domini attraverso un trust non transitivo e potenzialmente elevare i privilegi all'interno della foresta del dominio fidato. Tutti i dettagli della issue sono riportati di seguito.

Dopo aver segnalato il problema a Microsoft, ho ricevuto la seguente risposta:

Figura 1. Risposta dell'MSRC
Figura 1. Risposta dell'MSRC

Poiché Microsoft ha stabilito che il problema non influisce sulla sicurezza e quindi non prevede di modificare il comportamento, non c'è modo di evitare il problema, a parte semplicemente non utilizzare trust esterni.

Trust e transitività

Nota: questo post presuppone una conoscenza di base dei trust e del loro funzionamento (per ulteriori informazioni su questi argomenti, suggerisco di leggere l'eccellente post di Will Schroeder sui trust). Il post non tratta i trust intra-forestali (cioè i trust all'interno di una singola foresta), se non per quanto riguarda lo specifico percorso di attacco discusso, né i trust di autenticazione selettiva, che sono incredibilmente rari negli ambienti reali.

I restanti trust sono forest trust e trust esterni.

  • I forest trust sono trust tra due foreste. Più precisamente, sono trust transitivi tra i domini radice di due foreste. Qualsiasi utente di qualsiasi dominio della foresta fidata può autenticarsi in qualsiasi dominio della foresta fidata.
  • I trust esterni sono trust tra due domini. Questi trust non sono transitivi. Solo gli utenti del dominio fidato possono autenticarsi esclusivamente rispetto al dominio fidato (Figura 2).
Figura 2. Trust esterno non transitivo
Figura 2. Trust esterno non transitivo

Microsoft descrive la transitività dei trust come segue:

La transitività determina se un trust può essere esteso al di fuori dei due domini con cui è stato formato.

  • Un trust transitivo può essere utilizzato per estendere le relazioni di fiducia con altri domini.
  • Un trust non transitivo può essere utilizzato per negare relazioni di fiducia con altri domini.

Questa descrizione è chiara: per i trust non transitivi, solo i due domini coinvolti nel trust possono autenticarsi a vicenda, e non è possibile andare oltre.

Purtroppo, come dimostrerò in questo post, non è così.

Impostazione lab

Per dimostrare correttamente il problema dei trust non transitivi ho impostato il lab con diverse foreste multidominio che condividono trust esterni (Figura 3).

Figura 3. Configurazione lab
Figura 3. Configurazione lab

Questa configurazione coinvolge tre (3) foreste. Due (2) delle foreste contengono tre (3) domini. La terza foresta contiene due (2) domini. I domini semperis.lab e treetest.lab condividono un trust esterno bidirezionale non transitivo (Figura 4).

Figura 4. Trust esterno 1
Figura 4. Trust esterno 1

Anche i domini grandchild1.child1.semperis.lab e semperisaz.lab condividono un trust esterno bidirezionale non transitivo (Figura 5).

Figura 5. Trust esterno 2
Figura 5. Trust esterno 2

Questa configurazione consente di dimostrare le implicazioni e i limiti del problema dei trust non transitivi.

Come funziona l'autenticazione cross-trust di Kerberos

Per autenticarsi a un servizio attraverso un trust utilizzando Kerberos è necessario un referral (noto anche come referral Ticket Granting Ticket [TGT]). Si tratta di un ticket richiesto dal controller di dominio (DC) locale per il dominio estero. Per dimostrare come vengono eseguite le richieste di ticket tra i trust questa sezione si concentra sulla foresta semperis.lab. Tuttavia, queste informazioni sono applicabili a qualsiasi percorso di trust "consentito".

Nota: questo post presuppone una comprensione di base del normale flusso di autenticazione Kerberos (per una spiegazione dettagliata di tale flusso, si veda il post Detecting Kerberoasting Activity di Sean Metcalf). Nel resto del post si utilizza Rubeus per la richiesta manuale dei ticket.

L'esempio più semplice di autenticazione cross-trust è l'autenticazione di un servizio su un dominio che ha un trust diretto con il dominio locale. Il trust che il dominio grandchild1.child1.semperis.lab ha con child1.semperis.lab (Figura 5) è un esempio di questo tipo di trust. In questa situazione, dopo aver ottenuto un TGT iniziale, il primo passo per ottenere un ticket di servizio per un account di grandchild1.child1.semperis.lab verso un servizio di child1.semperis.lab è ottenere un referral per child1.semperis.lab (Figura 6, Figura 7).

Figura 6. Richiesta di referral per child1.semperis.lab
Figura 6. Richiesta di referral per child1.semperis.lab
Figura 7. Richiesta di referral
Figura 7. Richiesta di referral

La richiesta è stata fatta a un DC (SGC1DC1.grandchild1.child1.semperis.lab) all'interno del dominio(grandchild1.child1.semperis.lab) locale dell'utente che si autentica (lowpriv). La richiesta è stata fatta per il servizio krbtgt/child1.semperis.lab. Il fatto che il ServiceRealm (srealm) sia il dominio locale (grandchild1.child1.semperis.lab) all'interno del ticket risultante dimostra che questo ticket è un referral.

Questo riferimento può ora essere utilizzato per richiedere ticket di servizio (ST) dal DC esterno (SC1DC1.child1.semperis.lab) per l'host di servizio/SC1DC1.child1.semperis.lab (Figura 8, Figura 9).

Figura 8. Esempio di utilizzo del referral
Figura 8. Esempio di utilizzo del referral
Figura 9. Richiesta di ST tramite referral
Figura 9. Richiesta di ST tramite referral

Per fare un ulteriore passo avanti, se è necessario un servizio sul dominio radice della foresta (semperis.lab), non è possibile richiedere un riferimento per questo dominio direttamente dal dominio locale (grandchild1.child1.semperis.lab). Un riferimento per krbtgt/semperis.lab viene richiesto dal DC locale sgc1dc1.grandchild1.child1.semperis.lab. Tuttavia, il DC restituisce un ticket per il servizio krbtgt/child1.semperis.lab, indicando che questo referral è per il dominio child1.semperis.lab, non per semperis.lab (Figura 10, Figura 11).

Figura 10. Richiesta di referral per semperis.lab
Figura 10. Richiesta di referral per semperis.lab
Figura 11. Richiesta di referral per semperis.lab
Figura 11. Richiesta di referral per semperis.lab

È possibile verificare il problema provando a utilizzare questo ticket per richiedere un ST per il dominio semperis.lab. In questo modo si ottiene un errore AP_ERR_BAD_INTEGRITY. Questo perché il ticket di riferimento è crittografato con la chiave di fiducia per il trust grandchild1.child1.semperis.lab -> child1.semperis.lab. I DC del dominio radice semperis.lab non conoscono questa chiave e quindi non sono in grado di decifrare il ticket (Figura 12, Figura 13).

Figura 12. Richiesta di dominio radice ST
Figura 12. Richiesta di dominio radice ST
Figura 13. Richiesta di ST da semperis.lab
Figura 13. Richiesta di ST da semperis.lab

Per richiedere un ticket di servizio per il dominio radice semperis.lab è necessario prima richiedere un referral per semperis.lab da un DC nel dominio child1.semperis.lab, utilizzando questo referral. La Figura 14 e la Figura 15 mostrano una richiesta fatta al DC esterno (sc1dc1.child1.semperis.lab), utilizzando il referral per il dominio child1.semperis.lab per richiedere un ulteriore referral per il dominio root semperis.lab.

Figura 14. Richiesta di referral per semperis.lab
Figura 14. Richiesta di referral per semperis.lab
Figura 15. Richiesta di referral per semperis.lab
Figura 15. Richiesta di referral per semperis.lab

Si noti che per richiedere questo ticket è necessaria l'opzione /dominio di destinazione. Per impostazione predefinita, Rubeus utilizza il dominio all'interno del ticket che è stato passato per compilare il dominio nella TGS-REQ. In questo caso, il dominio sarebbe grandchild1.child1.semperis.lab e si otterrebbe un errore ERR_WRONG_REALM perché il dominio locale DC è child1.semperis.lab. Questa informazione è rilevante per la sezione seguente.

Infine, il referral risultante per semperis.lab può essere utilizzato per richiedere ST per il dominio semperis.lab. La Figura 16 mostra la richiesta di ST effettuata dall'utente lowpriv@grandchild1.child1.semperis.lab al DC SDC1.semperis.lab per l'host SPN/SDC1.semperis.lab. Poiché il percorso di fiducia è consentito, questa richiesta è andata a buon fine anche se i due domini coinvolti non hanno un trust diretto (Figura 17).

Figura 16. Richiesta ST per semperis.lab
Figura 16. Richiesta ST per semperis.lab
Figura 17. Richiesta di ST per host/sdc1.semperis.lab
Figura 17. Richiesta di ST per host/sdc1.semperis.lab

Questo metodo di richiesta di referral per i domini fidati può essere seguito per richiedere ST per qualsiasi servizio all'interno di qualsiasi dominio per il quale è consentito il percorso di fiducia.

Rendere transitivi i trust non transitivi

Quindi, come è possibile attraversare i trust esterni per autenticarsi a domini che dovrebbero essere proibiti?

I domini semperisaz.lab e grandchild1.child1.semperis.lab hanno un trust esterno bidirezionale. Pertanto, dopo aver recuperato un TGT per qualsiasi account all'interno del dominio semperisaz.lab, è possibile richiedere un referral per grandchild1.child1.semperis.lab (Figura 18, Figura 19).

Figura 18. Referral a granchild1.child1.semperis.lab
Figura 18. Referral a granchild1.child1.semperis.lab
Figura 19. Richiesta di referral per grandchild1.child1.semperis.lab
Figura 19. Richiesta di referral per grandchild1.child1.semperis.lab

Questo riferimento può essere utilizzato per richiedere ST per servizi sul dominio grandchild1.child1.semperis.lab. Tuttavia, un tentativo di ottenere un riferimento ad altri domini all'interno della stessa foresta (ad esempio, child1.semperis.lab) restituisce, come previsto, l'errore ERR_PATH_NOT_ACCEPTED (Figura 20).

Figura 20. Errore di percorso non accettato
Figura 20. Errore di percorso non accettato

Questo errore si verifica perché il trust semperisaz.lab -> granchild1.child1.semperis.lab non è transitivo. Pertanto, il percorso da semperisaz.lab a figlio1.semperis.lab non è consentito (Figura 21).

Figura 21. Richiesta di referral per child1.semperis.lab
Figura 21. Richiesta di referral per child1.semperis.lab

Tuttavia, è possibile richiedere un TGT locale per grandchild1.child1.semperis.lab. Si tratta di un TGT locale perché, a differenza del referral, che ha un ServiceRealm (srealm) di semperisaz.lab, il ServiceRealm di questo TGT è grandchild1.child1.semperis.lab (Figura 22, Figura 23).

Figura 22. Richiesta di TGT locale per grandchild1.child1.semperis.lab
Figura 22. Richiesta di TGT locale per grandchild1.child1.semperis.lab
Figura 23. Richiesta di un TGT locale
Figura 23. Richiesta di un TGT locale

Utilizzando questo TGT locale è ora possibile richiedere un referral per child1.semperis.lab (Figura 24, Figura 25).

Figura 24. Referral per child1.semperis.lab
Figura 24. Referral per child1.semperis.lab
Figura 25. TGT locale per la richiesta di referral per child1.semperis.lab
Figura 25. TGT locale per la richiesta di referral per child1.semperis.lab

Ora si dispone di un riferimento utilizzabile che può essere usato per richiedere ST per child1.semperis.lab con qualsiasi account del dominio semperisaz.lab e senza apportare modifiche ai trust o agli account in AD. Le Figure 26 e 27 mostrano una richiesta di ST dal DC sc1dc1.child1.semperis.lab per il servizio host/sc1dc1.child1.semperis.lab come utente lowpriv@semperisaz.lab.

Figura 26. Richiesta di ST per DC in child1.semperis.lab
Figura 26. Richiesta di ST per DC in child1.semperis.lab
Figura 27. Richiesta di ST per host/sc1dc1.child1.semperis.lab
Figura 27. Richiesta di ST per host/sc1dc1.child1.semperis.lab

Inoltre, questo metodo può essere utilizzato per spostarsi in qualsiasi dominio all'interno della stessa foresta in cui esiste grandchild1.child1.semperis.lab. Possiamo dimostrarlo richiedendo un referral al dominio radice semperis.lab. È stato richiesto un referral per semperis.lab dal DC sc1dc1.child1.semperis.lab come utente lowpriv@semperisaz.lab (Figura 28, Figura 29).

Figura 28. Richiesta di referral per semperis.lab
Figura 28. Richiesta di referral per semperis.lab
Figura 29. Richiesta di referral a semperis.lab
Figura 29. Richiesta di referral a semperis.lab

Fortunatamente, con questo metodo non è possibile saltare attraverso altri trust al di fuori della foresta (trust esterni o forest trust). Come mostra la Figura 3, il dominio radice semperis.lab ha un trust esterno bidirezionale con treetest.lab. Questo trust può essere utilizzato per dimostrare questa limitazione (Figura 30, Figura 31).

Figura 30. Richiesta di referral per treetest.lab
Figura 30. Richiesta di referral per treetest.lab
Figura 31. Richiesta di referral per treetest.lab
Figura 31. Richiesta di referral per treetest.lab

In tal modo almeno si impedisce a un aggressore che utilizza questo metodo di effettuare il trust hopping in un'altra foresta. Tuttavia, questo problema di trust non transitivi è chiaramente utile per gli aggressori che cercano di elevare i privilegi all'interno di una foresta da una parte all'altra del trust. Gli aggressori potrebbero interrogare le informazioni sui domini presumibilmente non ammessi, interrogare domini più sensibili o con una sicurezza potenzialmente più debole, o eseguire attacchi Kerberoasting o coercizione dell'autenticazione NTLM su domini che si presume siano non ammessi.

Domain hopping

Sebbene gli aggressori non possano spingersi oltre utilizzando solo il metodo descritto in questo post, il problema potrebbe aprire nuove vie di attacco. In precedenza ho scritto un post che dimostrava la possibilità di creare account macchina attraverso i trust e le relative implicazioni. Incorporando quel metodo di domain hopping con questo nuovo metodo, è possibile superare la limitazione descritta alla fine della sezione precedente.

Utilizzando il referral recuperato per semperis.lab (alla fine della sezione precedente), è possibile richiedere un ticket per il servizio LDAP su un DC di semperis.lab. In questo caso, è stato richiesto un ST per ldap/sdc1.semperis.lab utilizzando il riferimento per semperis.lab come utente lowpriv@semperisaz.lab (Figura 32, Figura 33).

Figura 32. Richiesta ST per ldap
Figura 32. Richiesta ST per ldap
Figura 33. Richiesta ST per ldap/sdc1.semperis.lab
Figura 33. Richiesta ST per ldap/sdc1.semperis.lab

Questo ST può essere iniettato e utilizzato per creare un account macchina direttamente in semperis.lab se la configurazione consente gli Utenti autenticati, che sono l'impostazione predefinita (Figura 34).

Figura 34. Creare un account macchina in semperis.lab
Figura 34. Creare un account macchina in semperis.lab

Questa azione fa sì che il DC sdc1.semperis.lab crei l'account macchina TestComp all'interno del dominio semperis.lab (Figura 35).

Figura 35. Creazione dell'account macchina TestComp
Figura 35. Creazione dell'account macchina TestComp

Il nuovo account macchina TestComp è un account locale all'interno del dominio semperis.lab. Ora è possibile recuperare un TGT per questo account macchina (Figura 36, Figura 37).

Figura 36. Account macchina TGT
Figura 36. Account macchina TGT
Figura 37. Richiesta di TGT per TestComp
Figura 37. Richiesta di TGT per TestComp

Questo account macchina TGT è autorizzato a richiedere un referral al dominio fidato treetest.lab. L'account macchina TGT può essere utilizzato per richiedere un referral per il dominio treetest.lab dal DC SDC1.semperis.lab (Figura 38, Figura 39).

Figura 38. Richiesta di referral per treetest.lab
Figura 38. Richiesta di referral per treetest.lab
Figura 39. Richiesta di referral per treetest.lab
Figura 39. Richiesta di referral per treetest.lab

Infine, la issue descritta in questo post può essere utilizzata per ottenere l'accesso al dominio inaccessibile dsptest.lab. Innanzitutto, si richiede un TGT locale per treetest.lab. Il TGT locale viene richiesto utilizzando il riferimento per treetest.lab come account TestComp$@semperis.lab dal DC TDC1.treetest.lab (Figura 40, Figura 41).

Figura 40. Richiesta del TGT locale per treetest.lab
Figura 40. Richiesta del TGT locale per treetest.lab
Figura 41. Richiesta del TGT locale per treetest.lab
Figura 41. Richiesta del TGT locale per treetest.lab

Quindi, utilizzare questo TGT locale per richiedere un referral per dsptest.lab. Le Figure 42 e 43  mostrano che è stato richiesto un referral per il dominio dsptest.lab dal DC TDC1.treetest.lab come utente TestComp$@semperis.lab.

Figura 42. Richiesta di referral per dsptest.lab
Figura 42. Richiesta di referral per dsptest.lab
Figura 43. Richiesta di referral per dsptest.lab
Figura 43. Richiesta di referral per dsptest.lab

Chiaramente, la combinazione di questi due metodi potrebbe rendere possibile un accesso molto profondo alle infrastrutture aziendali AD, utilizzando qualsiasi account a basso privilegio su un dominio che abbia un trust esterno verso qualsiasi dominio all'interno di una foresta.

Rilevamento della vulnerabilità della transitività dei trust

Purtroppo, vista la risposta di Microsoft, l'unico modo per evitare il problema è rimuovere i trust esterni.

Se non è possibile rimuovere tutti i trust esterni, è necessario monitorare l'evento 4769 di Windows (è stato richiesto un ticket di assistenza Kerberos). La prima indicazione da ricercare è che è stato richiesto un TGT locale da un account in una foresta diversa (Figura 44).

Figura 44. 4769 per il TGT locale
Figura 44. 4769 per il TGT locale

In questo caso, il campo Account Domain è un dominio che appartiene a una foresta diversa e il Service Name è krbtgt. Questo evento è seguito da un altro evento 4769, che richiede un referral (Figura 45).

Figura 45. 4769 per il referral
Figura 45. 4769 per il referral

In questo caso, Account Domain è un dominio all'interno di una foresta diversa, e  Service Name è un altro dominio nella foresta locale.

Si noti che questi due eventi possono verificarsi su DC diversi all'interno dello stesso dominio. Non è necessario che gli eventi si verifichino sullo stesso DC. A questo punto, qualsiasi ST richiesto (evento 4769) che utilizza questo riferimento avrà un Account Domain che contiene un dominio che non deve essere autorizzato ad autenticarsi nel dominio locale.

Il monitoraggio di questi eventi e il rilevamento di questo tipo di attacchi sono previsti in una futura versione di Semperis, Directory Services Protector (DSP).

Di chi ci si può fidare?

Come si può notare, la descrizione ufficiale dei trust esterni non transitivi è fuorviante. Allo stato attuale, quando si crea un trust esterno non transitivo, si deve accettare che qualsiasi account all'interno del dominio fidato sia in grado di autenticarsi contro qualsiasi dominio all'interno dell 'intera foresta in cui risiede il dominio fidato.

Come dimostrato più sopra in questo post, la prassi migliore è quella di impedire agli utenti autenticati di creare account macchina. In caso contrario, non solo i domini all'interno della foresta sono più a rischio di attacco, ma anche i domini (e la foresta in cui risiedono) che hanno un trust esterno con qualsiasi dominio all'interno della foresta sono più a rischio a causa della possibilità di creare account macchina attraverso i trust e di autenticarsi rispetto a domini che dovrebbero essere disabilitati (ulteriori informazioni sulla quota dell'account macchina e su come impedire la creazione di account macchina con privilegi bassi sono disponibili nell'eccellente post di Kevin Robertson "MachineAccountQuota is USEFUL Sometimes").

Se non altro, spero che questo post informi gli amministratori di sistema del rischio reale a livello di foresta che comporta l'implementazione di trust esterni.

Cronologia

  • 4 maggio 2022: creato il caso MSRC
  • 12 maggio 2022: lo stato del caso è stato modificato in "Review/Repro".
  • 17 giugno 2022: lo stato del caso è stato modificato in "Developed" con un'e-mail in cui si affermava: "Abbiamo confermato il comportamento segnalato. Continueremo le nostre indagini e decideremo come affrontare il problema".
  • 17 giugno 2022: lo stato del caso è stato modificato in "Completed - Resolved".
  • 24 agosto 2022: commento lasciato sul caso per conoscere il suo stato di avanzamento.
  • 2 settembre 2022: commento di follow-up lasciato sul caso per conoscere lo stato del caso.
  • 14 settembre 2022: invio di un'e-mail di follow-up per conoscere lo stato del caso.
  • 29 settembre 2022: ricevuta un'e-mail in cui si spiega che il problema non ha influito sulla sicurezza.
  • 7 marzo 2023: divulgazione al pubblico.

Ringraziamenti

Per saperne di più

Ti interessano altre ricerche sulla sicurezza di Active Directory? Consulta questi articoli.