Skip to main content

Snyking in – Exploitation d’une vulnérabilité ReDoS dans le package ms

Écrit par
Snyking in small

13 mars 2019

0 minutes de lecture

Bienvenue dans une nouvelle édition de notre série d’exploits Snyking In ! La dernière fois, nous avons examiné l’exploitation d’une vulnérabilité de traversée de répertoires dans la bibliothèque st. Dans cet épisode, nous nous intéressons à la vulnérabilité par déni de service liée aux expressions régulières, montrons comment l’exploiter et présentons les risques potentiels pour vos données et vos systèmes.

Nous vous montrerons également comment détecter et corriger ce type de vulnérabilité dans votre application. Sans plus attendre, voici la vidéo de démonstration de l’exploit, suivie d’informations complémentaires sur la vulnérabilité par déni de service liée aux expressions régulières.

Snyking In - Regular Expression Denial of Service vulnerability exploit in the ms package

Déni de service par expression régulière

Le déni de service (DoS) désigne une famille d’attaques visant à rendre un système inaccessible à ses utilisateurs légitimes. Il existe de nombreux types d’attaques DoS : certaines cherchent à saturer les canaux réseau d’un système en générant un volume important de trafic depuis plusieurs machines (attaque par déni de service distribué, ou DDoS), tandis que d’autres envoient des requêtes conçues pour provoquer le plantage du système ou lui faire prendre un temps disproportionné pour les traiter.

Le déni de service par expression régulière (ReDoS) est un type d’attaque par déni de service. Les expressions régulières sont extrêmement puissantes, mais peu intuitives ; elles peuvent donc finir par permettre à des attaquants de rendre votre site inaccessible.

Le récent rapport sur l’état de la sécurité de l’open source publié par Snyk montre que les divulgations de vulnérabilités par déni de service liées aux expressions régulières ont augmenté de 143 % au cours de la seule dernière année.

Graphique linéaire intitulé « Les divulgations de vulnérabilités par déni de service par expression régulière (ReDoS) sont en hausse », montrant leur augmentation : 14 en 2016, 30 en 2017 et 72 en

Retour arrière catastrophique

Examinons l’expression régulière suivante :

regex = /A(B|C+)+D/

Cette expression régulière permet de vérifier les éléments suivants :

  • A La chaîne doit commencer par la lettre A

  • (B|C+)+ La chaîne doit ensuite contenir, après la lettre A, soit la lettre B, soit une ou plusieurs occurrences de la lettre C (le + correspond à une ou plusieurs occurrences). Le + à la fin de cette partie indique que celle-ci peut être répétée une ou plusieurs fois.

  • D Enfin, nous vérifions que cette partie de la chaîne se termine par un D

L’expression correspondrait à des entrées telles que ABBD, ABCCCCD, ABCBCCCD et ACCCCCD. Dans la plupart des cas, un moteur d’expressions régulières trouve une correspondance très rapidement :

$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
0.04s user 0.01s system 95% cpu 0.052 total

$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
1.79s user 0.02s system 99% cpu 1.812 total

Le test d’une chaîne de 30 caractères prend environ 52 ms au total. Mais lorsqu’on lui fournit une chaîne invalide, le test prend près de deux secondes, soit plus de dix fois le temps nécessaire pour tester une chaîne valide. Cette différence spectaculaire s’explique par la façon dont les expressions régulières sont évaluées.

La plupart des moteurs d’expressions régulières fonctionnent de manière très similaire, à quelques différences près. Le moteur choisit la première façon possible de faire correspondre le caractère en cours, puis passe au suivant. S’il ne parvient pas à faire correspondre ce caractère, il revient en arrière pour vérifier s’il existe une autre façon d’interpréter le caractère précédent. S’il s’engage trop loin dans une piste avant de constater que la chaîne ne correspond finalement pas, et si plusieurs caractères admettent plusieurs chemins d’expression régulière valides, le nombre d’étapes de retour en arrière peut devenir très élevé : c’est ce qu’on appelle un retour arrière catastrophique.

L’exploit ms

La commande suivante ajoute une tâche à faire dans notre application Snyk Goof. Le passage in 20 minutes du texte est reconnu par le moteur d’expressions régulières comme une indication de temps. La logique métier de l’application pourrait, par exemple, s’en servir pour créer des rappels ou des alertes.

$ echo 'content=Call mom in 20 minutes' | http --form http://localhost:3001/create -v

Nous pouvons essayer de déterminer par force brute la longueur de l’entrée de la tâche comme suit. La commande affiche 60 000 5 comme nombre de minutes, mais elle s’exécute très rapidement, car le motif correspond toujours.

$ echo 'content=Buy milk in '`printf %.0s5 {1..60000}`' minutes' | http --form http://localhost:3001/create -v

Pour provoquer un déni de service, il faut transmettre une chaîne qui entraîne un scénario de retour arrière catastrophique. Il faut notamment une longue chaîne d’entrée, comme dans l’exemple précédent, mais aussi veiller à ce que le moteur d’expressions régulières ne trouve jamais de correspondance, afin qu’il explore toutes les possibilités avant d’échouer. C’est ce qui provoque le délai, autrement dit le déni de service recherché. Pour cela, nous pouvons remplacer le texte minutes par minutea, par exemple, un motif auquel le moteur d’expressions régulières ne trouvera aucune correspondance. La commande ci-dessous provoquera un déni de service d’environ 10 à 15 secondes. Si nous transmettons 600 000 5, nous devrons attendre une bonne partie de la journée que le serveur traite la requête.

$ echo 'content=Buy milk in '`printf %.0s5 {1..60000}`' minutea' | http --form http://localhost:3001/create -v

Pour tester votre application et détecter les vulnérabilités dans ses bibliothèques tierces, telles que ms, essayez Snyk gratuitement.

Lancez-vous dans les compétitions Capture The Flag

Apprenez à résoudre des défis de capture du drapeau en regardant à la demande notre atelier virtuel d’initiation.