There be trolls ahead!
With the Pentesting with Kali (PWK) course complete and Offensive Security Certified Professional (OSCP) certification successfully achieved (write-up here), I now find myself in a state of limbo, asking myself “where to from here?”. There are a number of choices I need to make, and finding an answer to my questions is going to take some careful deliberation and time commitment. So whilst I ponder the why/who/where’s, I will be expending some random keystrokes concentrating on owning vulnhub boxes, ensuring I continue to keep my offsec tools sharpened.
The first of these boxen will be Tr0ll: 1.
The description from the author, Maleus (@maleus) is as follows:
Tr0ll was inspired by the constant trolling of the machines within the OSCP labs.
The goal is simple, gain root and get Proof.txt from the /root directory.
Not for the easily frustrated! Fair warning, there be trolls ahead!
Let the troll hunting begin!
First things first; what boxes are on the network? A quick and easy tool to achieve this is an ARP scanner tool called netdiscover
.
With our target host (172.16.66.131) found, let’s enumerate which ports are open with nmap
. I like to start with a full TCP portscan…
… followed by executing an NSE script category known as vuln.
FTP
(21), SSH
(22), HTTP
(80). Let’s start by opening a browser session to the webserver:
Nice… a taunting troll straight of the bat. From the NSE vuln scripts, we can see that the http-enum.nse
script has found one file (robots.txt) and a directory (/secret/) of interest. Let’s take a quick look at the robots.txt file:
1 2 |
User-agent:* Disallow: /secret |
Nothing overly exciting there apart from the mention of a directory called /secret
, which we have already enumerated. Let’s take a look at it:
Mad? Not yet, but I get a sneaking suspicion that I will be well and truly over trolls by the end of this. While it doesn’t look like HTTP
is going to give us any immediate love, I always like to enumerate files/directories as much as I can just to make sure. My brute-force tool of choice at the moment is wfuzz
, although you could achieve the same, if not similar results using OWASP’s Java driven GUI tool DirBuster
or a CLI tool such as dirb
.
Nothing new there unfortunately. Let’s move on to one of the other ports we exposed during our enumeration stage, FTP
. The obvious first stage is to check if anonymous FTP
is enabled:
Good… we have anonymous FTP
access. We do a directory listing and notice a file which may be of interest, lol.pcap
. Next step, download the file and open it with wireshark
. Looking at the capture file, we can see that someone has previously connected to the FTP server, and downloaded a file named secret_stuff.txt
. From our previous directory listing, we know that this file no longer exists, so let’s take a look at the TCP stream. Frame 40
contains our ftp-data
, and looking a little deeper into the packets we see the following content:
Well, well, well, aren't you just a clever little devil, you almost found the sup3rs3cr3tdirlol :-P\n\nSucks, you were so close... gotta TRY HARDER!\n
Arghhhhh…. “Try Harder” comes back to haunt me. sup3rs3cr3tdirlol
hey? Sounds like a web directory to me.. let’s take a look.
Onwards and upwards as they say. Let’s download the roflmao
binary and take a look at what hints it may hold for us. For me, whenever I want to know more about a binary, I initially use the strings
tool to find any printable characters. Running a strings on our roflmao
binary returns the following:
Nothing overly interesting here. If we execute the binary, it will return “Find address 0x0856BF
to proceed” to stdout. Having checked the FTP/HTTP/SSH
services, I am not aware of any direct vulnerability/exploit which can be leveraged, which leads me to believe the address of 0x0856BF
could be a another ‘secret’ directory which was not exposed during my previous dictionary attack with wfuzz
. Let’s browse to the address as a directory:
Interesting. Having a look in the good_luck/
directory we find a file name which_one_lol.txt
with the following content:
What about the other directory, this_folder_contains_the_password
? Hmm… it contains a file named Pass.txt
with contents as follows:
Usernames and password perhaps? Let’s add all of the strings from which_one_lol.txt
to a file called users
, and the string Good_job_:)
to a file called pass
. We haven’t found any cgi-bin
or other HTTP
authentication method, so we’ll concentrate on brute-forcing FTP
and SSH
with these credentials. My tool of choice for brute-forcing basic services is ncrack
. You could also use tools such as hydra
or medusa
. First up, FTP
:
No luck there. Let’s try SSH
:
No luck here either. Not due to the username/password combination being incorrect, but due to some type of lock out after x
amount of failed SSH
attempts. What a pain in the proverbial! I reboot the vulnerable VM and attack again, with the same result, confirming ‘something’ is killing our sessions after failed attempts. I’d put money on fail2ban
being the culprit, but we’ll know for sure when we get a shell on this trolling box.
So what next? As the box is called tr0ll
, I’m pretty certain SSH
access via the found credentials is the answer, mainly due to the fact that it’s causing so much frustration. I painstakingly ssh
to the host going through each usernames manually, with a password of Good_job_:)
. By the time I get to the end of the usernames, and after many frustrating reboots of the VM, I have two light bulb moments! Firstly, the author of the vulnerable host, Maleus, has a website called overflowsecurity.com. One of our possible usernames, and last in the list, was 'overflow'
! The second light bulb moment was around the directory name of the possible password: this_folder_contains_the_password
. Could it be that Pass.txt
is the password, not the contents of the file?!
I bounce the VM one more time and attempt to ssh
onto the host with a username of overflow
and a password of Pass.txt
:
BAM! We have a low privileged shell…. well… for a short period.
Something is killing our SSH
session periodically. We’ll get to that soon, but let’s continue to follow process. Once I get a privileged shell the very first part of my enumeration towards privilege escalation is look for any setuid
files we can leverage from.
Nothing out of the ordinary stands out there. Next step is to look for the ‘unusual’. In this case, we have already identified ‘something’ is killing our sessions periodically, so let’s take a look at crontab
.
According to the cronlog
, a script located in /lib/log/
is being called every two (2) minutes; cleaner.py
. Let’s take a closer look at this script:
Looking at the code, every two (2) minutes the script, executed as root
, removes any files in /tmp
. Clever. /tmp
is the common directory where any exploit code or privilege escalation scripts are generally stored due to the permissions of the folder. Not so clever, is the chmod 777
permissions given to the file, which in theory will allow us to edit the file. Voila! Thanks to poor permissions on the file, we are able to edit the file, which should be executed with root
permissions. Now, during my enumeration stage, I found another binary which is not ‘normal’, lmao.py
in /opt
. Due to the root
permissions on this file, I was unable to look at what the python
script actually did, so leveraging upon the crontab
execution of cleaner.py
, I cat
the script and redirect the output to /tmp/out.txt
. Once executed, out.txt
contained the following python code:
1 2 3 4 5 6 |
#!/usr/bin/env python import os os.system('echo "TIMES UP LOL!"|wall') os.system("pkill -u 'overflow'") sys.exit() |
This annoying troll code was the reason we were getting session disconnects! The cronlog
did not include this file in it’s output, so it can only be assumed root’s crontab
is executing the file. Troll… arghhhhh!
Let’s get root!! Enter stage left what I call the setuid
C Wrapper fatality move! I have used the following snippet of code more times than I care to count in order to obtain privilege escalation on *nix hosts. It’s tried, tested, and dependable.
1 2 3 4 |
int main(void) { setgid(0); setuid(0); system("/bin/bash"); } |
As you can see, this script will execute /bin/bash
with setgid/setuid
of 0
, aka root
. All we need to do is compile the C code, and coerce root into changing the ownership and sticky bit, enabling a normal user to execute the script and obtain a root
shell. Sounds wordy, but it’s not that complicated. To do this, we edit /lib/log/cleaner.py
with the our chown/chmod commands, and let crontab
perform it’s periodic magic.
1 2 3 4 5 6 7 |
#!/usr/bin/env python import os import sys try: os.system('chown root:root /tmp/privshell; chmod 4755 /tmp/privshell') except: sys.exit() |
The end result? A setuid
binary as follows, which, when executed by our standard user overflow
will give us a root
shell.
We have root
and we have the flag! Wooohooooo! The end I hear you say? Not for me… I need to put this troll to rest! crontab -e
and let’s get rid of the damn lmao.py
script from trolling sessions! :)
Now it’s the end. The tr0ll
has been slain! And for the record, it was fail2ban
that was limiting our SSH
brute-force attempts also.
Thank you so much Maleus for the challenge. It was great fun and lived up to it’s name of tr0ll. Thanks vulnhub for making the challenges available.
Until next time, tight lines and may you pop shells often.
Quick FYI, I couldn’t get your modified cleaner.py script to work without adding “cat” in front of “/opt/lmao.py”,
Thanks for the heads up Greg.. you’re right, the working script has a cat in there.