SwampCTF 2024
I recently participated in SwampCTF , a 2-day student-run CTF put on by the University of Florida’s Student Information Security Team . Our team was madeup of a handful of students from CCSO , and we were able to place 34th out of 362 participating teams. This CTF was really well run, and the challenges were fun and pretty unique.
Ping Pong - Forensics
Prompt: What happened to my traffic??? The pings?!?? They're taking over!!!! They're... ping... pong pingpong ping find my pong flag.
We’re provided with a pcap with almost exclusively ICMP traffic. After examining a couple, it looked like they contained a base64 payload broken up across the packets. The last one in particular gave it away wiith the charictaristic ==
.
I cooked up a little python script to fetch the data field from each ICMP packet and output them to a file.
1 | from scapy.all import * |
I tossed the payload into CyberChef, decoded the base64, and downloaded the resulting image which contained the flag, yippee!
Easy Pwn - Pwn
Prompt: Pwn can be a pretty intimidating catagory to get started in. So we made a few chals to help new comers get their feet wet!
This was a pretty easy buffer overflow attack, we’re provided with a host to netcat to and a source c file.
1 | int user_option; |
The code used for the server looks to be vulnerable to a buffer overflow (clearly), due to the use of gets to fill the username buffer. If we provide more input than expected, it’ll write a nonzero value to isAdmin and print the flag.
Employee Evaluation - Pwn
Prompt:
1 | This company sucks. They're ranking all the employees against one another, and they keep putting security to the sideline. The CISO told me that they don't care about actual code quality, just fancy buzzwords and looking nice. I want to get out of here, but I can't without this dang secret code. It's for, uh, good things, and not sharing secrets. This exposed evaluation script seems like a good start. Can you help me out? |
Connecting to the provided host gives us the following output:
1 | ❯ nc chals.swampctf.com 60010 |
From the prompt we can assume it’s running in a bash environment, I provided | whoami
as initial output to see what it would spit out.
1 | | whoami |
It looks like our output is getting substituted inside of a variable using the syntax ${employee_[input]_score}
, we need to find a way to break out of that and get the flag output.
I went with the payload adam_score}$(sh -c env)#
. adam_score}
finished the line with a legit employee value, and $(sh -c env)
should output the environment variables. The trailing #
will comment out the rest of the line and ensure our command is run.
1 | ❯ nc chals.swampctf.com 60010 |
New C2 Channel? - Forensics
Prompt: Sometimes you can exfiltrate data with more than just plain text. Can you figure out how the attacker smuggled out the flag on our network?
The provided pcap only contained some HTTP traffic, and following the stream to look at the contents didn’t yield anything interesting:
1 | GET /index.php?username=&page=.d8888.........88P.888..........P..888..88888b.....888..888."88b8888888.888..888...888..888.d88P...888..88888P".........888....8........888.............888..... HTTP/1.1 |
The URI for the get request looked really funky, so i used Wireshark to filter to only get requests with http.request.method == "GET"
. I went down a whole rabbit hole trying to script out the process of examining the URIs which wasn’t really needed.
Script Solution (Scrapped)
My initial thought was to script out the process of getting the requested URI’s, so I could look at the output. This ended up being way overkill and not helpful, but here’s the script I used:
1 | from scapy.all import * |
Then I used awk to cleanup the output awk -F 'page=' '{print $2}' ./http_get_uris.txt > awked_http_get.txt
, so I had all the cleaned up URIs in a file. It didn’t display correctly and was a PITA to format.
Simple Solution
When the script output wasn’t easily read I went back to Wireshark… I realized that you can literally hold the right arrow button and see the flag in ASCII art in Wireshark’s data section.
I manually transcribed it and called it a day.
Notoriously Tricky Login Mess - Forensics
Part 1 - Username
Prompt:
1 | We found out a user account has been compromised on our network. We took a packet capture of the time that we believe the remote login happened. Can you find out what the username of the compromised account is? |
The provided packet capture had a bunch of HTTP traffic which was using NTLM for authentication.
I only saw 2 users, Administrator, and adamkadaban. Adamkadaban was the popped user.
Part 2 - Password
Prompt: Great job finding the username! We want to find out the password of the account now to see how it was so easily breached. Can you help?
From the NTLM challenge response authentication seen in the packet capture, we can extract the needed info to get a hash to crack and find the user’s password. I was initially looking for the format [Username]::[Domain Name]:[NTLM Server Challenge]:[NTProofSTR]:[NTLMv2 Response]
.
I got the resulting hash:
1 | adamkadaban::EC2AMAZ-E33SGL8::9860ff77ebae7c49::427e62eb532e7cf982af3a23fb5aa4b2::427e62eb532e7cf982af3a23fb5aa4b2010100000000000000a205e9c266da01e7973bcb0507f9230000000002001e0045004300320041004d0041005a002d00450033003300530047004c00380001001e0045004300320041004d0041005a002d00450033003300530047004c00380004001e0045004300320041004d0041005a002d00450033003300530047004c00380003001e0045004300320041004d0041005a002d00450033003300530047004c003800070008001998a3e4c266da010000000000000000 |
We threw a ton at this and it didn’t crack. The formatting was in fact wrong. What Wireshark was tagging as the domain name was in fact the host name. Switching to the following hash cracked it with rockyou:
1 | adamkadaban:::1fed9e8e0ca470a3:98ebffae0b77865893846dfadb757cfb:0101000000000000801c50dbc266da0188d48d08eff230a80000000002001e0045004300320041004d0041005a002d00450033003300530047004c00380001001e0045004300320041004d0041005a002d00450033003300530047004c00380004001e0045004300320041004d0041005a002d00450033003300530047004c00380003001e0045004300320041004d0041005a002d00450033003300530047004c003800070008005783ebd6c266da010000000000000000 |
Off The Hook - Rev
Prompt: We did some dabbling with apk's, have fun!
I opened the provided swamp.apk
with VSCode using the APKTool extension. CTRL + Shift + P > Open an APK
, will allow you to decompile an APK to java source, edit the app, etc.
There was an overwhelming amount of source files, and frankly I had no clue what I was looking for. I searched through all the files swamp
and found MainActivity.java
.
This file notably contained the getFlag function:
1 | public String getFlag() { |
I created a new file in the project, Solve.java
, to output the flag and skip all the checks:
1 | package com.rumpelstiltskin; |
Running this allowed me to get the flag without having to run/compile/deal with the app itself:
Potion Seller - Web
Prompt: My potions would kill you, traveler. You cannot handle my potions.
Browsing to the provided site, we’re greeted with a simple JSON output:
We’re provided with the source for the server which has a couple notable endpoints.
Endpoints
Checkout:
1 | app.get('/checkout', (req, res) => { |
In order to get the flag, it looks like we need to checkout while possessing the SwampShade potion, and not having any debt.
Buy:
1 | const potions = [ |
The SwampShade potion costs 100 gold, but we have none…
Borrow:
1 | app.get('/borrow', (req, res) => { |
Repay:
1 | app.get('/repay', checkUserSession, (req, res) => { |
The meat of the issue here is with the repay endpoint. The program checks to see if the user has enough gold to pay back the amount requested, and then sets the full amount of the debt to 0. So if a user has a debt of 50, and pays pack 5, it will wipe all the debt.
Solution
To get the flag we need to:
- Take out a loan
- Buy the SwampShade potion
- Repay the loan (exploiting the bad logic)
- Checkout
First I took out a loan for 101 gold with http://chals.swampctf.com:64845/borrow?amount=101
.
Next, I bought the SwampShade potion with http://chals.swampctf.com:64845/buy?id=4
.
Then, I repaid 1 gold, which zeroed out the remaining debt with http://chals.swampctf.com:64845/repay?amount=1
.
Finally, we’re able to checkout and get the flag, yippee!
- Title: SwampCTF 2024
- Author: Liam Geyer
- Created at : 2024-04-07 00:00:00
- Updated at : 2024-12-07 10:14:14
- Link: https://lfgberg.org/2024/04/07/ctfs/swamp-24/
- License: This work is licensed under CC BY-NC-SA 4.0.