Space Fleet Command
===============================
On commence par analyser le code de l'application.
On a un serveur nginx et un serveur web en JS.
Et on a une page pour report un problème, cela ressemble fort à une XSS avec exfiltration de cookie admin.
Cependant il y a un CSP a bypass :
.. code-block:: javascript
res.setHeader("Content-Security-Policy", "default-src 'self'; script-src 'none';")
On a une injection dans message :
Extrait du fichier app.js
.. code-block:: javascript
app.post('/report', (req, res) => {
const url = req.body.url;
if (!url) {
return res.status(400).send('Missing URL');
}
const path = extractPath(url);
if (!path) {
return res.render('pages/report', { message: `The URL ${url} is not valid.` });
}
visit(path, TOKEN, CHALLENGE_HOST)
.then(() => {
res.render('pages/report', { message: `The page was visited by our admin. We'll get back to you soon.` });
})
.catch((error) => {
console.error('Error visiting URL:', error);
res.render('pages/report', { message: `An error occurred while visiting the URL ${url}.` });
});
});
Fichier reports.ejs :
.. code-block:: console
<%- include('../partials/header', { title: 'Report an Issue' }) %>
🛑 Report Incorrect Information
<%- include('../partials/footer') %>
Mais cela ne semble pas exploitable directement car le bot ne voit pas le message, a moins que.
On sait que url.parse est déprécié :
.. code-block:: console
const parsedUrl = url.parse(urlString); //who cares about deprecation anyway
Et surtout on ne vérifie que "http:" et pas "http://"
.. code-block:: console
if (!(parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:')) {
return null;
}
- https://fr.claroty.com/team82/research/exploiting-url-parsing-confusion
- https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf
Après plusieurs essaies on découvre que :
- http:a/test ==> http://spacefleetcommand.404ctf.fra/test
- http:@test.test/a ==> http://spacefleetcommand.404ctf.frt@test.test/a
- http:@ahvce.free.beeceptor.com ==> http://spacefleetcommand.404ctf.frt@ahvce.free.beeceptor.com ==> Connexion sur ahvce.free.beepceptor.com
On peut donc rediriger le bot sur un endpoint de notre choix.
A partir de la, on peut exploiter une CSRF pour qu'il utilise lui même /report avec une url invalide mais qui contiendra notre "XSS".
Notre CSRF :
.. code-block:: console
Mais il y a le CSP donc la XSS est impossible, on peut uniquement faire une injection HTML.
A partir de la, on peut faire chercher au bot le flag, et tenter d'exfiltrer le contenu.
La requête de recherche renvoie 200 si elle trouve un résultat et 404 si elle ne trouve rien.
Ce qu'on a trouvé de mieux :
https://www.cse.chalmers.se/research/group/security/pdf/data-exfiltration-in-the-face-of-csp.pdf
.. code-block:: console
==> KO
==> KO
==> fonctionne dans l'injection html pour redirect
==> KO, redirection dans tous les cas que l'objet se charge ou pas
==> KO, redirection dans tous les cas que l'embed se charge ou pas
==> Ok mais inutile si on petu pas forcer soumission du formulaire, pas très utile
On utilise object qui se charge ou ne se charge pas selon le résultat 200 / 404, mais on ne trouve aucun moyen d'obtenir une exfiltration même en dns-prefetch.
On a trouvé ceci, peut être une dernière chance : https://github.com/cure53/HTTPLeaks/blob/main/leak.html
On envoie tout en CSRF au bot
Voici ce qui permet de faire des requêtes vers l'extérieur malgré la CSP :
.. code-block:: console
Bon maintenant comment forcer son activation ou sa désactivation ?
On a remarque qu'iframe fait également une requête DNS, donc on va combiner object et iframe :
.. code-block:: console
Si pas de requête DNS, alors c'est le bon caractère.
On va donc les tester un par un avec ce CSRF qu'on héberge sur un serveur beeceptor.com, et on envoie le bot dessus grâce à http:@fleetcmd.free.beeceptor.com :
.. code-block:: console
Après 1h30 a faire des requêtes, alors qu'on aurait pu automatiser lol, on obtient le flag : **404CTF{a24beb7d0b425ee7}**