
Trouver les expressions régulières vulnérables à ReDoS (déni de service par expression régulière)

Trouvez les regex vulnérables au déni de service par expression régulière (ReDoS).
Plus d'informations sur le blog de Doyensec
De nombreux analyseurs d'expressions régulières par défaut ont une complexité dans le pire des cas illimitée. La correspondance d'une regex peut être rapide lorsque la chaîne d'entrée correspond. Cependant, certaines chaînes d'entrée non correspondantes peuvent amener le moteur de regex à entrer dans des boucles de backtracking folles et à prendre des heures pour traiter. Cela peut provoquer un déni de service, car le CPU sera bloqué à essayer de faire correspondre la regex.
Cet outil est conçu pour :
Cela reflète la complexité de la procédure de backtracking du moteur de regex par rapport à la longueur de la chaîne saisie.
Une complexité cubique signifie ici que si la partie vulnérable de la chaîne est doublée en longueur, le temps d'exécution devrait être environ 8 fois plus long (2^3).
Pour un ReDoS exponentiel avec des étoiles étoilées, par exemple (a*)*$, un facteur de correction est utilisé et la complexité sera supérieure à 10.
Pour l'exploitabilité, une complexité cubique ou plus est généralement nécessaire, sauf si des chaînes vraiment géantes sont autorisées en entrée.
Exécutez regexploit et entrez l'expression régulière v\w*_\w*_\w*$ dans la ligne de commande.
$ regexploit
v\w*_\w*_\w*$
Pattern: v\w*_\w*_\w*$
---
Worst-case complexity: 3 ⭐⭐⭐ (cubic)
Repeated character: [5f:_]
Final character to cause backtracking: [^WORD]
Example: 'v' + '_' * 3456 + '!'
La partie \w*_\w*_\w* contient trois groupes de répétition qui se chevauchent (\w correspond aux lettres, chiffres et tirets bas). Comme indiqué dans la ligne Repeated character: [5f:_], une longue chaîne de _ (0x5f) correspondra à cette section de nombreuses manières différentes. La complexité dans le pire des cas est de 3 car il y a 3 groupes infiniment répétés. Un exemple pour provoquer un ReDoS est donné : il se compose du préfixe requis v, d'une longue chaîne de _ puis d'un ! (caractère non-mot) pour provoquer le backtracking. Tous les ReDoS n'exigent pas un caractère particulier à la fin, mais dans ce cas, une longue chaîne de _ correspondra avec succès à la regex et ne fera pas de backtracking. La ligne Final character to cause backtracking: [^WORD] montre qu'un caractère non correspondant (pas un caractère de mot) est nécessaire à la fin pour empêcher la correspondance et provoquer un ReDoS.
Comme autre exemple, installez une version de module vulnérable au ReDoS comme pip install ua-parser==0.9.0.
Pour analyser les modules Python installés, exécutez regexploit-python-env.
Importing ua_parser.user_agent_parser
Vulnerable regex in /somewhere/.env/lib/python3.9/site-packages/ua_parser/user_agent_parser.py #183
Pattern: \bSmartWatch *\( *([^;]+) *; *([^;]+) *;
Context: self.user_agent_re = re.compile(self.pattern)
---
Worst-case complexity: 3 ⭐⭐⭐
Repeated character: [20]
Example: 'SmartWatch(' + ' ' * 3456
Worst-case complexity: 3 ⭐⭐⭐
Repeated character: [20]
Example: 'SmartWatch(0;' + ' ' * 3456
Vulnerable regex in /somewhere/.env/lib/python3.9/site-packages/ua_parser/user_agent_parser.py #183
Pattern: ; *([^;/]+) Build[/ ]Huawei(MT1-U06|[A-Z]+\d+[^\);]+)[^\);]*\)
Context: self.user_agent_re = re.compile(self.pattern)
---
Worst-case complexity: 3 ⭐⭐⭐
Repeated character: [[0-9]]
Example: ';0 Build/HuaweiA' + '0' * 3456
...
Pour chaque expression régulière vulnérable, il imprime une ou plusieurs chaînes malveillantes pour déclencher un ReDoS. Si vous définissez votre user-agent sur ;0 Build/HuaweiA000000000000000... et naviguez sur un site web utilisant une version ancienne de ua-parser, le serveur pourrait prendre beaucoup de temps à traiter votre requête, se terminant probablement par un statut 502.
Python 3.8+ est requis. Pour extraire les regex du code JavaScript/TypeScript, NodeJS 12+ est également requis.
Créez éventuellement un environnement virtuel
python3 -m venv .env
source .env/bin/activate
Maintenant, installez avec pip
pip install regexploit
Entrez les expressions régulières via stdin (une par ligne) dans regexploit.
regexploit
ou via un fichier
cat myregexes.txt | regexploit
Un support intégré existe pour analyser les regex à partir de code Python, JavaScript, TypeScript, C#, YAML et JSON.
Analyse le code Python (sans l'exécuter) via l'AST pour trouver les regex. Les regex sont ensuite analysées pour le ReDoS.
regexploit-py my-project/
regexploit-py "my-project/**/*.py" --glob
Cela utilisera le package NodeJS inclus dans regexploit/bin/javascript qui analyse votre JavaScript en tant qu'AST avec eslint et imprime toutes les regex.
Ces regex sont fournies au chercheur de ReDoS en Python.
regexploit-js my-module/my-file.js another/file.js some/folder/
regexploit-js "my-project/node_modules/**/*.js" --glob
N.B. il y a des différences entre l'analyse des regex javascript et python, donc il peut y avoir des erreurs. Je ne suis pas sûr de vouloir écrire un AST de regex JS !
Recherche des regex dans tous les modules Python actuellement installés dans votre chemin/env. Cela signifie que vous pouvez pip install les modules qui vous intéressent et ils seront analysés. Le code Cpython est inclus.
regexploit-python-env
N.B. cela n'analyse pas le code Python en un AST et ne trouvera que les regex compilées automatiquement lors de l'importation du module. Les modules sont effectivement importés, donc le code dans les modules sera exécuté. C'est utile pour trouver des regex qui sont construites à partir de petites chaînes au chargement, par exemple CVE-2021-25292 dans Pillow
Le support YAML nécessite pyyaml, qui peut être installé avec pip install regexploit[yaml].
regexploit-json *.json
regexploit-yaml *.yaml
regexploit-csharp something.cs
Cet outil a été créé par Ben Caller de Doyensec LLC pendant son temps de recherche.