OWASP : Pixi

Hey, in this post we are going to look at a few of the (intentionally many) vulnerabilities present in the Pixi webapp, created by the OWASP as a platform for people to learn what not to do when creating web applications.

Here is a summary :

Broken secret

When we create an account and login into the app, we are sent to the main page of the application :

On it, we see the expected menus, but one is out of the ordinary : Secret. When clicking on it, we get an error page :

This error page is not caused by us not being authorized to see the secret page, but by a coding error from the developer. It tells us that “server.conf” is not a function. What is it then ? if we try to go to /server.conf, we see this file :

And just like that, the secret used to create JWT tokens was leaked, meaning that we will now be able to create valid token for anything.

Reflected XSS

The search page is vulnerable to XSS injections, meaning that we could create a malicious link to the website with our payload, send it to another user, and their browser would execute that payload. For example, visiting http://172.17.0.1:8000/search/?query=%3Cscript%3Ealert(%27hi%27)%3C/script%3E gives us this :

Admin page bypass

Enumerating the website gives us the existence of the /admin page, which is probably an administration page. Since we don’t have admin rights on our account, trying to access this page returns us a json message indicating that we are not administrators :

However, this protection is poorly implemented, and only searches to match “admin”, this means that going to /Admin allows anyone to access the admin page :

CSRF to delete images

When we try to delete a photo we uploaded, we can see that a simple get request is made to /user_delete_photo/image_id.

However, when we try to delete an image that we do not own, we get an error, telling us that we do not own this image. What if someone posted a picture we don’t want online ? We could try to get them to send a request to this endpoint, and the photo would be deleted. Sending it directly would be too obvious. What we could do instead is host a webpage totally unrelated, and have one of the images have its source at http://172.17.0.1:8000/user_delete_photo/image_id. When the victim visits this page, their browser would make a GET request to this URL, deleting the image. This is made really easy by the website, since photo ids are shown along with the image on the main page.

For example, imagine the user bbabb uploaded photo 221 that we wanted to delete.

Here is a page we could create :

<p>HTTP 418 : I'm a teapot</p>
<img src="http://172.17.0.1:8000/user_delete_photo/221">

We host it using a python server :

python3 -m http.server 4445

When the victim visits http://maliciousserver.com/page.html, this is what he sees :

But, when he goes back to his images, image 221 is missing, and has been deleted :

This worked because Firefox sent the cookies for http://172.17.0.1 when making the request. On Chromium, this attack did not work, because the request did not include these cookies.

request on Firefox
request on Chromium

Decoding a JWT token

On the main page, we are told that Pixi now has an API, running on port 8090, and we are given a link to its documentation.

Using this knowledge, we can create an account, and login on the API to get a JWT token :

Since we know the JWT secret used (see here), we can decode this token and see what it holds :

We can see that a lot of information is stored on this token, a lot more that it should, which leads us to the next vulnerability.

Dumping any password

If we look at the documentation for the API, we see an endpoint /user/info which allows a user to get his account information by sending his JWT token. We know what the JWT holds, but this endpoint probably uses only the id when fetching user data, this means that by creating a new JWT token with random data and the id of the user we want the info about, we can get his email and password :

For example, using this payload in the JWT token :

{
  "user": {
    "_id": 25,
    "email": "[email protected]",
    "password": "aaaa",
    "name": "test",
    "pic": "https://s3.amazonaws.com/uifaces/faces/twitter/themadray/128.jpg",
    "is_admin": true,
    "account_balance": 49.70000000000002,
    "all_pictures": []
  },
  "iat": 1676024364
}

We can dump user 25 :


Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *