Playing with internal path traversal leads to a lot of fun

Table of Contents

Bonjour à tous :)

Ça fait un moment depuis mon dernier article, désolé pour ça !
Pour me faire pardonner, je vais parler d’une vulnérabilité plutôt sympa !
J’espère que vous allez aimer et que ça vous donnera des idées pour de futures vulnérabilités que vous trouverez :)

Appetizer

Cette histoire est à propos d’une vulnérabilité que j’ai découverte quand je passais du temps avec des amis.

Il y a une entreprise qui nous a payé un voyage à leur quartier général afin de parler de notre expérience et de notre vision des choses entre autre.

Mais, comme vous me connaissez, une des meilleures façons de s’amuser pour moi est de fouiller des applications pour trouver des vulnérabilités ;)

Primer

Avant toute chose, certains d’entre vous ne savent peut-être pas ce que j’appelle Internal Path Traversal et je tiens à clarifier ça.
En gros, une Path Traversal est, tout simplement, une vulnérabilité permettant de se déplacer de manière arbitraire dans les dossiers d’une application sans que cela ne soit prévu au départ.
Une Internal Path Traversal utilise le même principe, sauf qu’elle concerne l’appel fait par une application pour en atteindre une autre.
En gros, vous faites une requête sur l’application A qui envoie elle-même une requête sur l’application B en se servant généralement des paramètres que vous avez mis dans votre requête.
Voici un exemple un peu plus concret:

Client request
https://example.com/group.php?id=5&username=Kuromatae
Application call (expected)
https://api.example.com/Group/5/User/Kuromatae
Client (malicious)
https://example.com/group.php?id=5&username=Kuromatae/../../../6
Application call (result)
https://api.example.com/Group/5/User/Kuromatae/../../../6
Final call
https://api.example.com/Group/6

Retournons maintenant à nos moutons :)

Practice

Donc, j’ai commencé à travailler sur une application de cette société.

Celle-ci servait à recevoir des goodies en répondant à des questions pour gagner des points (une sorte de jeu, en somme).

Cette application a été faite en Next.js.

Pendant que je la fouillais, j’ai trouvé une action NextJS vulnérable à une Internal Path Traversal.

Comme vous pouvez le voir ici, si je fais ["410220460/../410220460"], j’ai exactement le même résultat que si j’avais simplement fait ["410220460"].
Ce qui m’a fait penser à une Path Traversal.

Pour être sûr, j’ai fait quelques tests et j’ai essayé de remonter jusqu’à la racine de l’application.
En faisant cela, elle m’a renvoyé son URL complète.

Vous vous demandez sûrement comment j’ai trouvé cette Internal Path Traversal au départ ?

Eh bien, je dirais que ce n’est pas forcément compliqué d’en trouver : il suffit de faire des choses similaires à ce que j’ai fait dans ma première capture d’écran et d’espérer que ça retourne les mêmes informations que si vous n’aviez rien rajouté…
Quand vous voyez que la réponse est la même que la requête initiale, alors vous allez plus loin pour être sûr que c’est bien une Path Traversal :)

Main Course

Après avoir trouvé que ce paramètre me donnait un point d’entrée vers une API interne, j’ai décidé de creuser plus et j’ai trouvé quelques informations intéressantes.

J’ai commencé par regarder la documentation de l’API CrowdTwist: https://docs.oracle.com/en/cloud/saas/marketing/crowdtwist-develop/Developers/UserActivities.html

Malheureusement, après avoir essayé tout ce que je pouvais, je n’étais pas capable de faire grand-chose de cette Path Traversal. Voici ce que j’ai découvert :

  • C’est une API CrowdTwist
  • On ne peut pas utiliser de méthode de requête différente
  • La clé API est envoyée directement en paramètre dans l’URL et donc il n’est pas possible d’ajouter des paramètres à notre requête
  • L’UserID peut prendre l’une des formes suivantes :
    • Third Party ID
    • CrowdTwist ID
    • Email Address
    • Mobile Phone Number
    • Facebook User ID
    • Twitter User ID
    • User Name

Évidemment, j’ai essayé énormément de choses et, comme il y avait un exemple d’UserID dans la documentation de l’API, j’ai même tenté un peu de brute force, mais sans succès…

Dessert

Pendant que j’étais en train de travailler sur cette application, j’ai dû poser pour faire des photos.
J’ai pris mon PC et j’ai continué à travailler pendant qu’on me prenait en photo et c’est là que mon cerveau a commencé à essayer plein de choses différentes.

En regardant comment les autres requêtes du site étaient faites, je me suis dit : " pourquoi ne pas essayer d’envoyer un deuxième paramètre ? "

Donc, c’est ce que j’ai fait et j’ai vu qu’une deuxième requête était effectuée dans la réponse.

Ma requête ressemblait à ceci:

[
	"410223480/../../../../../../../foobar",
	"xxxx"
]

Et la réponse reçue était :

0: ["$@1", ["NVkDou1nig_jVfc89raAl", null]]
1: {
    "survey": {
        "exception": "iapi_Version_Mismatch_Error",
        "script_uri": "http://[REDACTED].crowdtwist.com/foobar",
        "remote addr": "[REDACTED]"
    },
    "response": {
        "exception": "iapi_Version_Mismatch_Error",
        "script_uri": "http://[REDACTED].crowdtwist.com/foobar/response",
        "remote addr": "[REDACTED]"
    }
}

Mais, en voyant comment la réponse était faite, je me suis dit : " Qu’est-ce que ça donnerait avec un ID qui n’était pas censé avoir un deuxième paramètre ? “
Oui car, souvenez-vous, nous sommes dans une application qui nous demande de répondre à des questions, mais que se passe-t-il si l’ID que j’utilise ne s’attend pas à des réponses ?

Bingo !
La réponse divulguait mon UserID et, devinez quoi ? Il était Incremental ;)

Du coup, j’ai repris la documentation et, j’ai trouvé l’endpoint qui m’interessais: https://docs.oracle.com/en/cloud/saas/marketing/crowdtwist-develop/Developers/UserProfile.html

J’ai ensuite essayé la path traversal complète et… Ça a marché !

Je pouvais récupérer les PII de tous les utilisateurs de la plateforme :D

Digestive

Au final, cette vulnérabilité était très interessante et, m’a même permis de mieux comprendre comment fonctionne NodeJS.

Après la découverte de la vulnérabilité, j’ai bien mis une heure à comprendre comment tout cela etait ficelé / comment réussir à en faire quelque chose de concret !

Je tiens à remercier tous ceux qui etaient la pour partager ce moment ainsi que l’entreprise qui m’a invité pour passer un bon moment tous ensemble :)


Thank you for reading !
~ Kuromatae