
Encontre expressões regulares vulneráveis a ReDoS (Ataque de Negação de Serviço por Expressão Regular)

Encontre regexes vulneráveis a Negação de Serviço por Expressão Regular (ReDoS).
Mais informações no blog da Doyensec
Muitos analisadores de expressão regular padrão têm complexidade de pior caso ilimitada. A correspondência de regex pode ser rápida quando apresentada a uma string de entrada correspondente. No entanto, certas strings de entrada não correspondentes podem fazer com que o correspondente de expressão regular entre em loops de retrocesso loucos e demore muito para processar. Isso pode causar negação de serviço, pois a CPU ficará presa tentando corresponder a regex.
Esta ferramenta foi projetada para:
Isso reflete a complexidade do procedimento de retrocesso do correspondente de expressão regular em relação ao comprimento da string inserida.
Complexidade cúbica aqui significa que se a parte vulnerável da string tiver seu comprimento dobrado, o tempo de execução deve ser cerca de 8 vezes maior (2^3). Para ReDoS exponencial com estrelas aninhadas, ex.: (a*)*$, um fator de ajuste é usado e a complexidade será maior que 10.
Para explorabilidade, complexidade cúbica ou superior é tipicamente necessária, a menos que strings verdadeiramente gigantes sejam permitidas como entrada.
Execute regexploit e digite a expressão regular v\w*_\w*_\w*$ na linha de comando.
$ 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 + '!'
A parte \w*_\w*_\w*$ contém três grupos repetitivos sobrepostos (\w corresponde a letras, dígitos e sublinhados). Como mostrado na linha Repeated character: [5f:_], uma longa string de _ (0x5f) corresponderá a esta seção de várias maneiras diferentes. A complexidade de pior caso é 3, pois há 3 grupos infinitamente repetitivos. Um exemplo para causar ReDoS é fornecido: consiste no prefixo necessário v, uma longa string de _ e depois um ! (caractere não-palavra) para causar retrocesso. Nem todos os ReDoS exigem um caractere específico no final, mas neste caso, uma longa string de _ corresponderá à regex com sucesso e não retrocederá. A linha Final character to cause backtracking: [^WORD] mostra que um caractere não correspondente (não um caractere de palavra) é necessário no final para evitar a correspondência e causar ReDoS.
Como outro exemplo, instale uma versão de módulo vulnerável a ReDoS, como pip install ua-parser==0.9.0. Para examinar os módulos python instalados, execute 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
...
Para cada expressão regular vulnerável, ele imprime uma ou mais strings maliciosas para acionar o ReDoS. Definir seu user agent para ;0 Build/HuaweiA000000000000000... e navegar em um site que usa uma versão antiga do ua-parser pode fazer com que o servidor demore muito para processar sua solicitação, provavelmente resultando no status 502.
Python 3.8+ é necessário. Para extrair regexes de código JavaScript/TypeScript, NodeJS 12+ também é necessário.
Opcionalmente, crie um ambiente virtual
python3 -m venv .env
source .env/bin/activate
Agora instale de fato com pip
pip install regexploit
Insira expressões regulares via stdin (uma por linha) no regexploit.
regexploit
ou via um arquivo
cat myregexes.txt | regexploit
Há suporte embutido para analisar regexes a partir de Python, JavaScript, TypeScript, C#, YAML e JSON.
Analisa código Python (sem executá-lo) através do AST para encontrar regexes. As regexes são então analisadas para ReDoS.
regexploit-py my-project/
regexploit-py "my-project/**/*.py" --glob
Isso usará o pacote NodeJS incluído em regexploit/bin/javascript que analisa seu JavaScript como um AST com eslint e imprime todas as regexes.
Essas regexes são alimentadas no localizador de ReDoS em python.
regexploit-js my-module/my-file.js another/file.js some/folder/
regexploit-js "my-project/node_modules/**/*.js" --glob
N.B. existem diferenças entre a análise de regex javascript e python, portanto pode haver alguns erros. Não tenho certeza se quero escrever um AST de regex JS!
Pesquisa por regexes em todos os módulos python atualmente instalados no seu path/ambiente. Isso significa que você pode pip install quaisquer módulos de seu interesse e eles serão analisados. O código CPython está incluído.
regexploit-python-env
N.B. isso não analisa o código python em um AST e só encontrará regexes compiladas automaticamente na importação do módulo. Os módulos são realmente importados, portanto o código nos módulos será executado. Isso é útil para encontrar regexes que são construídas a partir de strings menores durante o carregamento, ex.: CVE-2021-25292 no Pillow
O suporte a YAML requer pyyaml, que pode ser instalado com pip install regexploit[yaml].
regexploit-json *.json
regexploit-yaml *.yaml
regexploit-csharp something.cs
Esta ferramenta foi criada por Ben Caller da Doyensec LLC durante o período de pesquisa.