Swamp CTF 2025
Hey, fellow hackers! 🏴☠️
This be r1pp3r of the fearsome crew P4rad0x, settin’ sail for SwampCTF 2025!. Each one is a puzzle waiting to be unraveled, a system daring us to dig deeper. ⚓️ Yo-ho, let the hunt begin! ⚔️
Web
Serialies

Accessing the web app at http://chals.swampctf.com:44444 gave a “Whitelabel Error Page” — classic Spring Boot placeholder.

Luckily, the source code was available for download. That’s where the real magic began.
Inside the Java source, we found the core controller: PersonController.java
💡 Interesting Observation: The
Job.init()method is called if provided — and this method has access to theresumeURIfield… 🔥
The application was deserializing full Java object trees from JSON input with polymorphic class support (@class). That meant we could provide custom objects and trigger method calls like job.init().
Payload to Leak Arbitrary Files:
We crafted a JSON payload to:
Create a
Personobject.Inject a
Jobobject with aresumeURIset tofile:///flag.txt.
On POSTing the payload to /api/person using curl ,
curl -X POST http://<machine-ip>/api/person -H "Content-Type: application/json" -d 'payload'
The server executed init() on our injected Job, which read the contents of file:///flag.txt into the resume field.
Output: Person has been created with ID: f436db4a-ed69-4884-9cd7-7432f32d59b5
Then a simple GET /api/person retrieved all Person objects — including our injected one — and the flag was now stored in the resume field.

swampCTF{f1l3_r34d_4nd_d3s3r14l1z3_pwn4g3_x7q9z2r5v8}
Hidden Message Board

In this challenge, I landed on a basic message board—nothing special at first glance. But viewing the source, I noticed a JavaScript function called checkCode() .

What it does:
It checks if an element (
printFlagSetup) has acodeattribute equal toG1v3M3Th3Fl@g!!!!If true, it calls
getFlag()and prints it

In the HTML source, there's a hidden tag like:
<printFlagSetup id="flagstuff" code>
So we edit the HTML in-browser:
<printFlagSetup id="flagstuff" code="G1v3M3Th3Fl@g!!!!">

Then, trigger the checkCode() function via by typing something in text area. Boom!.
swampCTF{Cr0ss_S1t3_Scr1pt1ng_0r_XSS_c4n_ch4ng3_w3bs1t3s}
Beginners Web

This one had a three flag parts hidden two are encrypted on the page.

First part was easy—it was in an HTML comment.
<!--Part 1 of the flag: w3b_"-->
Suspecting the rest might be buried in JavaScript, we dig into the browser’s Network tab and inspect the scripts being loaded. I uncover a class containing some interesting logic:

From this code, we can deduce:
The second and third segments are encrypted strings.
Both use AES encryption.
The key used to decrypt them is
"flagPart2_3".
To figure out the precise decryption parameters, I need to know which crypto library was used. The script references:
var $n = Yp(Sp());
Following the definition of Sp, we can see it loads a variety of modules:
"./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core", "./aes", ...
I wrote a quick Python script using pycryptodome to decrypt the base64 strings. Turns out they were using OpenSSL-compatible AES-CBC with salt.
Final Flags:
Part 2:
br0w53r5_4r3_Part 3:
c0mpl1c473d
So full flag was:
swampCTF{w3b_br0w53r5_4r3_c0mpl1c473d}
Editor

In this challenge, it was a WYSIWYG HTML editor. The challenge description hinted that the flag was in /flag.txt, but direct access was blocked.

Since the editor lets you inject HTML, I just typed:

And clicked it right there in the rendered output, the file loaded.

swampCTF{c55_qu3r135_n07_j5}
SwampTech Solutions

This one was juicier. I start off with a page where SwampTech Solutions welcoming us. Below the welcome message there is a login page for SwampTech employee

Inspection the login page gives us the guest creds guest:iambutalowlyguest

After logging in as guest, there is a button says if you are an admin, visit the admin page instead .
I am a guest now, but I liked to escalate privileges. I noticed a cookie named user .

user:084e0343a0486ff05530df6c705c8bb4 Looks suspiciously like an MD5 hash. A quick hash lookup tells us it’s MD5("guest").

So, I created a MD5 hash of "admin" and stored it in the value of user cookie. user:21232f297a57a5a743894a0e4a801fc3 . Changing the cookie to this gives us full admin access.

Inside the admin panel, there were several functionalities:
A file checker form
And API Action

This feature is added for the intern in the SwampTech Solutions.
The file checker form says the "flag.txt" file exists in the current directory. But just checking file existence doesn't help us actually read it. So I tried some classic tricks like:
flag.txt; cat flag.txt . No Luck!

Digging into the HTML source, I found a form that was simply marked hidden via CSS. It was a feedback form asking for name and email , action directs to process.php

I edited the HTML tag and submitted the form. Everything seems normal, but what stood out is how it submitted the data — as XML. Also the name value is reflected in the response.

This is a red flag!, for potential XXE vulnerabilities. When applications parse XML without proper configuration, attackers can inject external entities and access local files on the server.
To test for XXE, I crafted a basic payload to try reading /etc/passwd:

Submitted it… and boom! The contents of /etc/passwd were reflected in the response. Confrimed XXE vulnerability.
Now that we confirmed file access via XXE, the next goal was to grab flag.txt. Unfortunately, it threw an error. Because:
The server is running on PHP and uses stream wrappers
So, let's try the PHP filter trick to base64 encode the output so we can safely read it:

Success! It returned a base64 string: c3dhbXBDVEZ7VzByazFOZ19DSDQxTDVfPHI+X0Z1Tn0K
swampCTF{W0rk1Ng_CH41L5__FuN}
Forensics
Homework Help

I am provided with a .vhd file—essentially a virtual hard disk commonly used by virtual machines. The objective was to recover deleted data from this disk image. I booted up the Autopsy tool
Autopsy is a digital forensics tool that allows you to analyze disk images in a user-friendly graphical interface. It’s widely used by security professionals to:
View file system structures
Recover deleted files
Analyze timelines, user activity, and more

I loaded the .vhd file into Autopsy as a new case. After navigated through the filesystem view to the "Deleted Files" section. I noticed an interesting file called Hacking Notes.docx
Opened the document within Autopsy’s viewer and Boom! — found the flag
swampCTF{n0thing_i5_3v3r_d3l3t3d}
Preferential Treatment

This challenge handed us a .pcap (packet capture) file. The task was to extract a password from the captured network traffic.
First I opened the .pcap file in Wireshark and filtered traffic for SMB (Server Message Block) protocol, commonly used for file sharing in Windows environments.

There I spotted a groups.xml file transferred in the SMB stream and I followed the TCP stream to extract the file contents. The contents of the xml file has a interesting variable:
This cpassword field is an obfuscated password stored in the Windows Group Policy Preferences (GPP). It’s not truly encrypted—it uses a known AES key embedded in Microsoft documentation. Hence, it’s easily reversible.
Used the tool gpp-decrypt to decode it.
swampCTF{4v3r463_w1nd0w5_53cur17y}
Cryptography
Rock my password

In this challenge, I am provided with a long hash string and tasked with reversing it to reveal the original password.
Our goal was to recover the plaintext password and submit it in the format swampCTF{password}.
I am told that:
The password is 10 characters long
It's sourced from the popular wordlist: rockyou.txt
First step, To make the cracking process more efficient, I filtered rockyou.txt to include only those passwords that are exactly 10 characters long.
This significantly reduced the number of candidates for our brute-force attempt:
Next Step is to find the password, based on the challenge description, I reverse-engineered the hashing logic:
First, the password is wrapped like this:
swampCTF{password}The resulting string is hashed:
100 times with MD5
100 times with SHA-256
100 times with SHA-512
The final hash result must match the one provided in the challenge.
I wrote a Python script to automate this layered hashing process:
Running the script yielded the matching password:
swampCTF{secretcode}
Misc
Pretty Picture: Double Exposure

In this challenge, I am given a suspiciously small PNG image named double-exposure.png along with the following hint:
"Hidden in the bits below, an image waits to be shown."
This says it is a steganography challenge right away. The challenge name, "Double Exposure" hinted at hidden content layered within the pixel structure, possibly in the individual RGB bit planes.
To start off, I ran exiftool to analyze the image metadata:
Nothing out of the ordinary popped up. It was a simple 200x200 PNG with RGBA color and 8-bit depth.
Then I turned to Stegsolve, a classic steganography analysis tool used to visualize different color and bit planes of an image.

Mostly the flag was visible in the all the planes but a little blurry. After cycling through the RGB planes manually for visible flag:
Green Plane 0 exposed part 1 of the flag.
Red Plane 1 exposed part 2 of the flag.


Each plane revealed a segment of the full flag, but neither alone gave the full picture. When I combined the revealed segments:
swampCTF{m3ss4g3s_0r_c0de_c4n_b3_h1dd3n_1n_1m4g3s}
Blue

The "Blue" challenge dropped me into the world of Azure Blob Storage with very little to go on: just a name—swampctf—and a nudge that this involved Azure cloud infrastructure.
This is a very interesting challenge and I learned something new in this challenge.
Without login credentials or internal access, this was a black-box challenge, and the key lay in discovering misconfigured public blob storage and this excellent reference saved the day:
Reference: Azure Pentesting – Exploiting Anonymous Access to Blob Storage
Step 1: Probe Known Containers
I tested for the existence of the default $logs container, which is automatically created in many Azure storage accounts:
https://swampctf.blob.core.windows.net/$logs?restype=container&comp=list

This returned a response with ResourceNotFound This message confirming anonymous access was enabled for this storage account. That meant other containers could potentially be listed or accessed.
“PublicAccessNotPermitted” message when the anonymous access is disabled
Step 2: Bruteforce Container Names
With this in mind, I used ffuf to fuzz for more blob container names:
Boom! I discovered a container named test with status 200 OK, meaning it was publicly accessible.
Step 3: Explore Discovered Container
Navigating to: https://swampctf.blob.core.windows.net/test

I found a file inside. Opening it revealed the flag!
swampCTF{345y_4zur3_bl0b_020525}
Osint
Party Time!

In this challenge, I am provided with a .HEIC image file titled party_time.HEIC, and the goal was to determine the GPS coordinates of where the picture was taken.
.HEIC is a High-Efficiency Image Format used commonly by iPhones. These files often retain rich metadata, including GPS data, which can be useful for forensic or OSINT analysis.
I used the exiftool utility to inspect the image file:
Among the metadata fields, we found the GPS information:
GPS Latitude:
29 deg 39' 10.32" NGPS Longitude:
82 deg 19' 59.68" W

Plugging these coordinates into Google Maps pinpointed a location in Florida.
The challenge asked for the coordinates in decimal format (approx):
swampCTF{29.39,82.19}
Party Time! Level 2

This was a continuation of the previous challenge, where the task was to identify the nearest fast-food restaurant to the discovered GPS coordinates.

From the previous location, I looked up nearby eateries using Google Maps and all I found closest fast-food chain to the location is turned out to be Checkers.

Upon checking the Google Maps reviews for the Checkers location, one of the reviews cheekily contained the flag.
swampCTF{Checkers_Yum}
Pwn
Beginner Pwn

In this challenge, I am provided with a binary file and the corresponding C source code.
This program simulates a basic login scenario. It requests a username input and determines whether the user is an administrator based on a bool is_admin flag. If the user is marked as an admin, they are granted access to view the flag.
However, due to poor memory handling and lack of input validation, this binary is vulnerable to a classic stack-based buffer overflow.
The vulnerability lies in the following declaration within the main() function:
Here, the local variables are laid out sequentially on the stack:
Then, the user input is collected via scanf("%s", username);. This format specifier does not limit input length, meaning the user can overflow the 10-byte username buffer and overwrite adjacent stack memory—including the is_admin flag.
print_stack()
This debug function prints the contents of 14 bytes on the stack (from username[0] through is_admin[3]) in reverse, helping visualize how the overflow corrupts memory:
This is useful both for debugging and for seeing how overflowing characters affect memory past the intended buffer boundary.
Because the program does not bound the input, an attacker can input more than 10 bytes to overflow into the is_admin flag. In C, any non-zero value will evaluate as true for a boolean check, so simply writing 'A' (0x41) past username[9] is sufficient.
Example Exploit Input:
We initiated a connection to the remote challenge server using netcat:
Because the program accepts more characters then it has space to hold, you are able to corrupt the
is_adminboolean. And because in C, any Boolean value that isn't 0 is considered "True", it lets you through!
Now, is_admin becomes true, and the user gains access to the flag:
swampCTF{n0t_@11_5t@ck5_gr0w_d0wn}
Last updated
