Chapter II
Second part of the walkthrough-series for the AllEndEvent pentest challenge.
Last updated
Second part of the walkthrough-series for the AllEndEvent pentest challenge.
Last updated
If you have previously shut it down, remember to reset the mail server to its initial state. You can verify that the server is up and running when the website loads. Alternatively, use the root
credentials to log in and use the command su zimbra
followed by zmcontrol status
. Should you encounter any issues, try another reset or re-import the VM. The other two servers are more resilient to forced shut-downs.
Information that we've already gotten our hands on:
root
access on mail.allendevent.com
(10.0.5.6
)
FTP credentials for allendevent.com
(10.0.5.8
)
webdev:W3bD3vs4r34m4z!nG2023
Credentials for crm.allendevent.com
mshea:AllendeventIsTheBest1!
CRM (customer relationship management) was also mentioned on the allendevent.com
website
Since we already got full access to one server, let's see if we gained any additional reach.
Inspecting the network interfaces reveals a second network adapter. mail.allendvent.com
is dual-homed and acquired the IP 10.0.10.10/24
which is part of the internal AllEndEvent network.
Using basic bash commands we can start scanning the internal network for additional machines.
The above command basically calls ping -c 1 $ip
for every ip
in the range of 10.0.10.0/24
and prints the IP if the target responds.
This technique is called "living off the land" as we are leveraging existing tools on the server to conduct scanning. It may not be pretty or fast, but it gets the job done.
Three IPs seem to be alive in the internal network, one of which is the mail server. This leaves one of the other IP addresses for the internal network adapter of the web server. I will leave it as an exercise to the reader to use other living-off-the-land or pivoting techniques for determining which server is the right one. The easiest one being a simple FTP connection attempt to each.
Once we identified 10.0.10.20
as the internal address of the web server, we won't be able to do much with it. We can upload files to what appears to be webdev
's home directory, but that's about it. We'll put that in our notes and continue enumeration.
We got internal FTP acess to the web server.
Earlier we discovered an additional subdomain of allendevent.com
: crm.allendevent.com
. Let's see if there's an externally reachable domain by that name on the web server. We add the subdomain to our /etc/hosts
and see if anything new pops up.
Indeed, a SuiteCRM login panel appears.
But we got something for that in our notes! Remember the mail from Margaret Shea - the sales lady - who had her password reset. Maybe she didn't choose a new one yet. Let's try the found combination.
User: mshea
Password: AllendeventIsTheBest1!
It seems we should definitely remind AllEndEvent to enforce a more strict password policy. For now we will continue enumeration though. After doing some research on SuiteCRM, what it is and what it does, let's check the installed version. Here it's a little bit easier than with Zimbra.
We identified a SuiteCRM v7.12.8 - and we got user access.
Equipped with a software name and version number, we are going to repeat looking for known vulnerabilities.
The above shows the first result on Google for "SuiteCRM CVE". CVE Details is a site that collects CVEs and let's you search through them by type and severity, among other things.
Your results may differ. New vulnerabilities will be released as time progresses.
The two CVEs at the top look promising. The base score of 6.5 seems rather low for code execution, but that's due to the fact that an authenticated user is required for exploitation. However, neither version matches.
There's a good chance that you will find another authenticated RCE on this list. One that matches the installed version. During the time of writing though, no CVE has been assigned to it yet.
As we did with Zimbra before, an alternative way to check for vulnerabilities is to look at the security advisories.
As we can see, there's a newer version with quite a lot of security fixes out there. However, SuiteCRM is keeping quiet about any details for now. Once CVEs have been released, they'll be populated with references to the report details.
We got two options here. Either we wait for the release of the details, read a write-up and use available exploits or we dig deeper ourselves. The latter is definitely more time consuming but also more fun.
Update: The vulnerability has now been released under CVE-2023-1034. Steps for finding a path to exploitation without a public CVE record were previously redacted but can now be accessed below.
I won't dive into all the details here, because that's what you can actually find in the report once it's released. For the sake of showcasing the exploit though, I'll cover the important steps.
First, SuiteCRM is open source, so we find their code on GitHub.
Looking at the commits between 7.12.8 and 7.12.9, we'll have to find the ones that might be related to security issues. Let's not pretend - this is a very tedious task. Even with just the few commits, there are a lot of changes. However, important security fixes tend to trigger a new release immediately, so it's a good idea to check the latest commits first.
Opening SuiteCRM 7.12.9 Release
shows "Showing 21 changed files with 339 additions and 95 deletions." on GitHub. That's a lot to look through.
Well, looks like we found the possible SQL injection that was mentioned. But that's actually not even the intended vulnerability. Bonus points!
Cutting to the chase, we find this:
Seems like module
was previously unsanitised and is now being checked to only consist of letters, dashes, underscores and dots. Let's see why they might have done that.
This part involves a lot of source code review, but eventually we can trace the following path of module
in v.7.12.8 before the changes.
Now we can see why module
is being sanitized in newer version. Because it's user input that is used to create a path for a require
statement. Again, I won't get into too much theory here. Since we can pass anything via the $_REQUEST['target_module']
parameter, we can use path traversal to achieve local file inclusion. However, it's rather limited because the ending is fixed to /language/en_us.lang.php
.
If we were able to upload a file called en_us.lang.php
in a directory named language
, we could probably get RCE by supplying a value like ../../../../../../../<path-to-language>/en_us.lang.php
to the request parameter target_module
.
Let's check our notes. Do we have some sort of file upload vulnerability in SuiteCRM? No we don't, but we got FTP access instead! The previous enumeration is paying off.
We identified a local file inclusion via path traversal that could lead to RCE by chaining it with a file upload.
Whether you got here by manual code review or CVE research, we're now ready for exploitation.
In order to properly access the internal FTP server, let's upgrade our previous reverse shell on the mail server to something fully interactive like SSH. This is also part of establishing persistence.
From the initial nmap
scans we could see that port 22 was already open, but SSH was not running. Let's modify the configuration of SSH to allow root
to log in and deploy an SSH key for easy access. The configuration file is at /etc/ssh/sshd_config
.
Let's try to connect via SSH with our private key.
With a stable and interactive shell, we're going to check out our FTP access. Instead of curl
, we'll be using the ftp
client though.
User: webdev
Password: W3bD3vs4r34m4z!nG2023
This does indeed look like the home directory of the webdev
user. More interestingly though, webdev
appears to be part of a system group with the id "48".
A quick Google search reveals that this ID usually belongs to the apache
user, which is responsible for the web service.
Our hopes rise as we realise that the web user has read access to the same directory we have write access to. Let's move on with exploitation and create the necessary files. First, we need a reverse shell payload.
Using a second terminal, we upload a standard PHP reverse shell that's integrated with Kali.
Now we update the configuration of the reverse shell: nano en_us.lang.php
on the mail server.
After we set the IP of Kali and chose a port, make sure to start a listener:
Let's upload the reverse shell to the FTP server.
Now we're ready to trigger the LFI in SuiteCRM. Tracing back the function calls, we see that the target_module
in SubpanelCreates.php
is used whenever we create a note for a call. I'll leave it to you to find alternative injection points.
Let's modify the value of target_module
to be:
Subsequently, send the request. Finally, we get a shell on the web server.
We successfully gained code execution as the low level web user apache
on the web server.
Being the web user is fine, but we're trying to get as much access as we possibly can. This means we're looking for ways to gain root
access. Once again, there's lots of things to try. I recommend you practice your manual enumeration skills before using automated scripts like linpeas
or exploit-suggester
.
Since this is a web server with two websites set up, let's take a look at their configuration. Especially since both WordPress and SuiteCRM require databases to store user data, configuration files may very well contain the credentials to access them.
Using Google or manual research, we identify the following config files of interest:
wp-config.php
in the WordPress installation directory
config.php
in SuiteCRM's installation directory
The websites are installed in /var/www/html
under allendevent.com
and crm.allendevent.com
respectively
We identified an additional set of cleartext credentials:
wp-root:1Sh0uld5t4rtU51nGKeep455n0?
and
crm-root:1H4t3MyJ0bL00lJustK1dd1ng!
Seems like the IT admin is not really content with his job - but that's none of our business.
Knowing that these credentials were likely created by the root
user, let's see if he reused any of his passwords.
We should probably remind the IT administrator to not reuse credentials. At least it was not AllendeventIsTheBest1!
though.
Password reuse finally gave us root
access to the web server.
Before we move on to yet another phase of enumeration, we will establish persistence via SSH once more. This time we already got root
's password but using keys is still the safe alternative.
Allow root
user to log in via SSH with keys (/etc/ssh/sshd_config
)
Upload the public key to /root/.ssh/
and add it to the authorized_keys
(make sure the directory and file have the correct permissions: 700
)
Enjoy SSH Access
If you paid attention during the mail server, you'll remember that root
access is worth enumerating again. In this case there are no stored credentials in the bash history, but we do find something similarly interesting.
.mozilla
is usually created by the Firefox browser and contains all the browser data. This is definitely worth looking into. Let's extract the entire directory with scp
and view it locally.
Well, besides looking at very important and beautiful cats for work, it seems that the root
user (which is likely to be the single IT administrator) has also bookmarked a tutorial for setting up an NFS server.
A quick look at the open ports on the web server with ss -tlpn
confirms, that there's no NFS running on the web server. There might be on the internal server though. But before we check that, let's take a look at the cached credentials: about:logins
.
We identified credentials for http://wiki.allendevent.com:54321
:
admin:Kn33sW34kM0ms5paghett1
Now, wiki.allendevent.com
is not inside the hosts
file on the web server, but we can safely assume this to be the remaining server on the internal network: 10.0.10.30
.
You may have discovered this hostname and website earlier already, if you thoroughly enumerated the internal network from the mail server. It has also been hinted at in the emails between James Hernandez and the manager.
This will be all for chapter II. In the next chapter we will continue on the internal network and exploit the final server.