# Regex Injection

## **📋 Índice**

1. [Fundamentos da Regex Injection](#-fundamentos-da-regex-injection)
2. [Mecanismos de Ataque](#-mecanismos-de-ataque)
3. [Vetores de Injeção por Linguagem](#-vetores-de-injeção-por-linguagem)
4. [Técnicas de Exploração](#-técnicas-de-exploração)
5. [Padrões de Ataque](#-padrões-de-ataque)
6. [Ferramentas de Detecção](#-ferramentas-de-detecção)
7. [Impacto e Consequências](#-impacto-e-consequências)
8. [Mitigações e Correção](#-mitigações-e-correção)
9. [Programação Segura](#-programação-segura)
10. [Checklists de Segurança](#-checklists-de-segurança)

***

## 🔬 **Ferramentas de Detecção (Continuação)**

### **Scanner de Regex Injection**

```python
#!/usr/bin/env python3
# regex_injection_scanner.py - Scanner de vulnerabilidades de regex injection

import re
import ast
import os
import sys

class RegexInjectionScanner:
    """Scanner para detectar vulnerabilidades de regex injection em código"""
    
    def __init__(self):
        self.vulnerabilities = []
        self.patterns = {
            'python': {
                'functions': ['re.search', 're.match', 're.fullmatch', 
                             're.compile', 're.sub', 're.subn', 're.split'],
                'dangerous_patterns': [
                    (r'f".*{.*}.*"', 'F-string com concatenação de input'),
                    (r'".*" \+ .*', 'Concatenação de strings com input'),
                    (r're\.\w+\(.*' + r'\+', 'Concatenação em chamada de função'),
                    (r're\.\w+\(.*%.*', 'Formatação com % em regex'),
                    (r're\.\w+\(.*format\(.*\)', 'String format em regex'),
                ],
                'safe_patterns': [
                    r're\.escape\(',
                    r'whitelist',
                    r'allowed_patterns',
                    r'preg_quote',
                ]
            },
            'javascript': {
                'functions': ['RegExp', 'match', 'replace', 'split', 'search'],
                'dangerous_patterns': [
                    (r'new RegExp\(.*\+', 'Concatenação em RegExp'),
                    (r'`.*\${.*}.*`', 'Template string com variável em regex'),
                    (r'/.*' + r'\+.*/', 'Concatenação literal'),
                ],
                'safe_patterns': [
                    r'escapeRegex',
                    r'\.replace\(/[.*+?^${}()|[\]\\]/g',
                    r'patterns\[',
                ]
            },
            'java': {
                'functions': ['Pattern.compile', 'matches', 'replaceAll', 'split'],
                'dangerous_patterns': [
                    (r'Pattern\.compile\(".*" \+ .*', 'Concatenação em Pattern.compile'),
                    (r'\.matches\(".*" \+ .*', 'Concatenação em matches'),
                ],
                'safe_patterns': [
                    r'Pattern\.quote',
                    r'Pattern\.LITERAL',
                ]
            },
            'php': {
                'functions': ['preg_match', 'preg_replace', 'preg_split', 'preg_grep'],
                'dangerous_patterns': [
                    (r'preg_\w+\(.*\$.*\)', 'Variável em regex'),
                    (r'preg_\w+\(.*\. \$', 'Concatenação em regex'),
                ],
                'safe_patterns': [
                    r'preg_quote',
                    r'PREG_LITERAL',
                ]
            }
        }
    
    def scan_file(self, filename, language='python'):
        """Escane

anhar um arquivo em busca de vulnerabilidades"""
        print(f"[*] Escaneando {filename}")
        
        try:
            with open(filename, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # Verificar padrões perigosos
            for pattern, description in self.patterns[language]['dangerous_patterns']:
                matches = re.finditer(pattern, content, re.IGNORECASE)
                for match in matches:
                    self.vulnerabilities.append({
                        'file': filename,
                        'line': self._get_line_number(content, match.start()),
                        'pattern': match.group(),
                        'description': description,
                        'severity': 'HIGH'
                    })
            
            # Verificar falta de sanitização
            for func in self.patterns[language]['functions']:
                if func in content:
                    # Verificar se há sanitização próxima
                    safe_patterns = self.patterns[language]['safe_patterns']
                    has_sanitization = any(sp in content[max(0, content.find(func)-200):content.find(func)+200] 
                                          for sp in safe_patterns)
                    
                    if not has_sanitization:
                        self.vulnerabilities.append({
                            'file': filename,
                            'function': func,
                            'description': f'Uso de {func} sem sanitização',
                            'severity': 'MEDIUM'
                        })
            
        except Exception as e:
            print(f"   ❌ Erro: {e}")
    
    def _get_line_number(self, content, position):
        """Obter número da linha a partir da posição"""
        return content[:position].count('\n') + 1
    
    def scan_directory(self, directory, language='python', extension=None):
        """Escane

anhar diretório recursivamente"""
        print(f"🔍 Escaneando {directory}")
        print("=" * 60)
        
        if not extension:
            extensions = {
                'python': ['.py'],
                'javascript': ['.js', '.jsx', '.ts', '.tsx'],
                'java': ['.java'],
                'php': ['.php']
            }
            extensions = extensions.get(language, ['.txt'])
        
        for root, dirs, files in os.walk(directory):
            for file in files:
                if any(file.endswith(ext) for ext in extensions):
                    self.scan_file(os.path.join(root, file), language)
        
        self._print_report()
    
    def _print_report(self):
        """Imprimir relatório de vulnerabilidades"""
        print("\n" + "=" * 60)
        print("📊 RELATÓRIO DE VULNERABILIDADES")
        print("=" * 60)
        
        if not self.vulnerabilities:
            print("✅ Nenhuma vulnerabilidade de regex injection encontrada")
            return
        
        print(f"🚨 {len(self.vulnerabilities)} vulnerabilidade(s) encontrada(s):\n")
        
        # Agrupar por severidade
        high = [v for v in self.vulnerabilities if v.get('severity') == 'HIGH']
        medium = [v for v in self.vulnerabilities if v.get('severity') == 'MEDIUM']
        
        if high:
            print("🔴 ALTA SEVERIDADE:")
            for vuln in high:
                if 'line' in vuln:
                    print(f"   📄 {vuln['file']}:{vuln['line']}")
                else:
                    print(f"   📄 {vuln['file']}")
                print(f"      {vuln['description']}")
                if 'pattern' in vuln:
                    print(f"      Padrão: {vuln['pattern'][:100]}")
                print()
        
        if medium:
            print("🟠 MÉDIA SEVERIDADE:")
            for vuln in medium:
                print(f"   📄 {vuln['file']}")
                print(f"      {vuln['description']}")
                print()

# Uso
if __name__ == "__main__":
    scanner = RegexInjectionScanner()
    if len(sys.argv) > 1:
        if os.path.isfile(sys.argv[1]):
            scanner.scan_file(sys.argv[1], sys.argv[2] if len(sys.argv) > 2 else 'python')
        else:
            scanner.scan_directory(sys.argv[1], sys.argv[2] if len(sys.argv) > 2 else 'python')
    else:
        print("Uso: regex_injection_scanner.py <arquivo|diretório> [linguagem]")
```

### **Ferramentas CLI de Detecção**

```bash
# Ferramentas para detectar regex injection

# 1. Semgrep - Análise estática
semgrep --config p/security --lang python --pattern 're.search($X, ...)' .
semgrep --config p/owasp-top-ten --lang javascript --pattern 'new RegExp($X)'

# 2. SonarQube - Análise contínua
sonar-scanner -Dsonar.projectKey=regex-injection -Dsonar.sources=.

# 3. Bandit (Python específico)
bandit -r . -f html -o report.html
bandit -r . -ll  # Apenas alta severidade

# 4. ESLint com regras de segurança
npm install -g eslint-plugin-security
eslint --plugin security --ext .js .

# 5. PMD para Java
pmd check -d src -R category/java/security.xml

# 6. Psalm para PHP
./vendor/bin/psalm --taint-analysis

# 7. Node.js security scanner
npm audit
npm audit fix --dry-run

# 8. Snyk para dependências
snyk test
snyk monitor

# 9. OWASP Dependency Check
dependency-check --scan . --format HTML

# 10. TruffleHog para secrets
trufflehog --regex --entropy=False .
```

***

## 💥 **Impacto e Consequências**

### **Matriz de Impacto**

```yaml
Impacto da Regex Injection:

  🔴 CRÍTICO:
    - DoS via ReDoS (servidor indisponível)
    - Bypass total de autenticação
    - Extração de dados sensíveis (senhas, tokens)
    - Injeção de código (PHP /e modifier)
    - Comprometimento da aplicação

  🟠 ALTO:
    - Bypass de validações de entrada
    - Exposição de informações do sistema
    - Corrupção de dados via regex maliciosa
    - Evasão de filtros de segurança

  🟡 MÉDIO:
    - Lentidão na aplicação
    - Consumo excessivo de CPU
    - Comportamento inesperado
    - Logs corrompidos

  🔵 BAIXO:
    - Falhas intermitentes
    - Erros de parsing
    - Comportamento não documentado
```

### **Cadeia de Ataque Completa**

```mermaid
graph TD
    A[Identificar endpoint com regex] --> B[Analisar construção da regex]
    B --> C{Input do usuário na regex?}
    
    C -->|Sim| D[Testar payloads de injeção]
    C -->|Não| E[Fim - não vulnerável]
    
    D --> F[Testar ReDoS]
    D --> G[Testar bypass]
    D --> H[Testar extração]
    
    F --> I[Monitorar tempo de resposta]
    G --> J[Verificar bypass de validação]
    H --> K[Verificar dados extraídos]
    
    I --> L{Exploração bem-sucedida?}
    J --> L
    K --> L
    
    L -->|Sim| M[Construir exploit final]
    L -->|Não| D
    
    M --> N[Executar ataque]
    N --> O[DoS / Bypass / Extração]
    
    style I fill:#ff9999
    style J fill:#ff9999
    style K fill:#ff9999
    style O fill:#ff6666
```

***

## 🛡️ **Mitigações e Correção (Continuação)**

### **Padrões Seguros por Linguagem**

```python
#!/usr/bin/env python3
# secure_regex_patterns_by_language.py - Padrões seguros por linguagem

class SecureRegexPatterns:
    """Implementações seguras de regex por linguagem"""
    
    @staticmethod
    def python_secure_patterns():
        """Padrões seguros em Python"""
        print("🐍 Python - Padrões Seguros")
        print("=" * 50)
        
        # 1. Usar re.escape
        def secure_search(user_input, text):
            escaped = re.escape(user_input)
            pattern = f".*{escaped}.*"
            return re.search(pattern, text)
        
        # 2. Usar whitelist de padrões
        VALIDATION_PATTERNS = {
            'email': re.compile(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'),
            'username': re.compile(r'^[a-zA-Z0-9_]{3,20}$'),
            'phone': re.compile(r'^\d{10,15}$'),
            'ip': re.compile(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'),
        }
        
        def validate_input(value, pattern_type):
            if pattern_type in VALIDATION_PATTERNS:
                return bool(VALIDATION_PATTERNS[pattern_type].match(value))
            return False
        
        # 3. Usar regex com timeout
        import signal
        class RegexTimeoutError(Exception):
            pass
        
        def regex_with_timeout(pattern, text, timeout=1):
            def timeout_handler(signum, frame):
                raise RegexTimeoutError()
            
            old_handler = signal.signal(signal.SIGALRM, timeout_handler)
            signal.alarm(timeout)
            
            try:
                result = re.search(pattern, text)
                return result
            except RegexTimeoutError:
                return None
            finally:
                signal.alarm(0)
                signal.signal(signal.SIGALRM, old_handler)
        
        print("   ✅ re.escape() para escapar input")
        print("   ✅ Whitelist de padrões predefinidos")
        print("   ✅ Timeout em operações regex")
    
    @staticmethod
    def javascript_secure_patterns():
        """Padrões seguros em JavaScript"""
        print("\n📜 JavaScript - Padrões Seguros")
        print("=" * 50)
        
        // 1. Escapar input
        const escapeRegex = (string) => {
            return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
        };
        
        // 2. Usar whitelist
        const VALIDATION_PATTERNS = {
            email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
            username: /^[a-zA-Z0-9_]{3,20}$/,
            phone: /^\d{10,15}$/
        };
        
        // 3. Usar limites de comprimento
        const safeRegex = (pattern, text, maxLength = 1000) => {
            if (text.length > maxLength) {
                throw new Error('Input too long');
            }
            return pattern.test(text);
        };
        
        console.log("   ✅ Escapar caracteres especiais");
        console.log("   ✅ Whitelist de padrões");
        console.log("   ✅ Limites de comprimento");
    
    @staticmethod
    def java_secure_patterns():
        """Padrões seguros em Java"""
        print("\n☕ Java - Padrões Seguros")
        print("=" * 50)
        
        // 1. Usar Pattern.quote()
        String userInput = ".*";
        String escaped = Pattern.quote(userInput);
        Pattern pattern = Pattern.compile(".*" + escaped + ".*");
        
        // 2. Usar Pattern.LITERAL
        Pattern literalPattern = Pattern.compile(userInput, Pattern.LITERAL);
        
        // 3. Usar whitelist
        private static final Map<String, Pattern> PATTERNS = new HashMap<>();
        static {
            PATTERNS.put("email", Pattern.compile("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"));
            PATTERNS.put("username", Pattern.compile("^[a-zA-Z0-9_]{3,20}$"));
        }
        
        System.out.println("   ✅ Pattern.quote() para escapar");
        System.out.println("   ✅ Pattern.LITERAL para match literal");
        System.out.println("   ✅ Whitelist de padrões");
    
    @staticmethod
    def php_secure_patterns():
        """Padrões seguros em PHP"""
        print("\n🐘 PHP - Padrões Seguros")
        print("=" * 50)
        
        // 1. Usar preg_quote()
        $userInput = ".*";
        $escaped = preg_quote($userInput, '/');
        $pattern = "/.*$escaped.*/";
        
        // 2. Usar PREG_LITERAL (PHP 7+)
        $result = preg_match("/$userInput/", $text, null, PREG_LITERAL);
        
        // 3. Desabilitar /e modifier
        ini_set('preg_replace_eval_modifier', '0');
        
        // 4. Limitar backtracking
        ini_set('pcre.backtrack_limit', 100000);
        ini_set('pcre.recursion_limit', 1000);
        
        echo "   ✅ preg_quote() para escapar\n";
        echo "   ✅ PREG_LITERAL para match literal\n";
        echo "   ✅ /e modifier desabilitado\n";
        echo "   ✅ Limites de backtracking configurados\n";

# Executar
SecureRegexPatterns.python_secure_patterns()
SecureRegexPatterns.javascript_secure_patterns()
SecureRegexPatterns.java_secure_patterns()
SecureRegexPatterns.php_secure_patterns()
```

### **Funções de Validação Seguras**

```python
#!/usr/bin/env python3
# safe_validation_functions.py - Funções de validação seguras

import re
import time
from functools import wraps

class SafeValidation:
    """Funções seguras para validação com regex"""
    
    def __init__(self, timeout=0.1):
        self.timeout = timeout
        self._init_patterns()
    
    def _init_patterns(self):
        """Inicializar padrões seguros"""
        self.safe_patterns = {
            # Padrões de validação comuns
            'email': re.compile(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'),
            'username': re.compile(r'^[a-zA-Z0-9_]{3,20}$'),
            'phone': re.compile(r'^\d{10,15}$'),
            'ipv4': re.compile(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'),
            'ipv6': re.compile(r'^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$'),
            'url': re.compile(r'^https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(/.*)?$'),
            'date_iso': re.compile(r'^\d{4}-\d{2}-\d{2}$'),
            'time_iso': re.compile(r'^\d{2}:\d{2}:\d{2}$'),
            'hex_color': re.compile(r'^#[0-9a-fA-F]{6}$'),
            'uuid': re.compile(r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'),
        }
    
    def validate(self, value, pattern_type):
        """Validar usando padrão predefinido"""
        if pattern_type not in self.safe_patterns:
            raise ValueError(f"Unknown pattern type: {pattern_type}")
        
        try:
            return bool(self.safe_patterns[pattern_type].match(value))
        except Exception:
            return False
    
    def search_safe(self, text, search_term):
        """Busca segura com escape"""
        escaped = re.escape(search_term)
        pattern = f".*{escaped}.*"
        return self._safe_regex(pattern, text)
    
    def replace_safe(self, text, search_term, replacement):
        """Substituição segura"""
        escaped = re.escape(search_term)
        pattern = escaped
        return self._safe_regex('sub', pattern, text, replacement)
    
    def _safe_regex(self, operation, pattern, text, *args):
        """Executar regex com timeout e validação"""
        # Validar comprimento do padrão
        if len(pattern) > 1000:
            print("⚠️  Pattern too long")
            return None
        
        # Validar caracteres permitidos
        allowed = r'^[a-zA-Z0-9_\s\-\.\,\*\+\?\(\)\[\]\{\}\|\\\/]+$'
        if not re.match(allowed, pattern):
            print("⚠️  Invalid characters in pattern")
            return None
        
        # Executar com timeout
        import signal
        
        class TimeoutError(Exception):
            pass
        
        def timeout_handler(signum, frame):
            raise TimeoutError()
        
        old_handler = signal.signal(signal.SIGALRM, timeout_handler)
        signal.alarm(int(self.timeout))
        
        try:
            if operation == 'search':
                return re.search(pattern, text)
            elif operation == 'match':
                return re.match(pattern, text)
            elif operation == 'findall':
                return re.findall(pattern, text)
            elif operation == 'sub':
                return re.sub(pattern, args[0] if args else '', text)
            return None
        except TimeoutError:
            print(f"⚠️  Regex timeout after {self.timeout}s")
            return None
        finally:
            signal.alarm(0)
            signal.signal(signal.SIGALRM, old_handler)
    
    def add_custom_pattern(self, name, pattern):
        """Adicionar padrão personalizado"""
        try:
            compiled = re.compile(pattern)
            self.safe_patterns[name] = compiled
            return True
        except re.error as e:
            print(f"❌ Invalid regex pattern: {e}")
            return False

# Exemplo de uso
validator = SafeValidation()

# Validação com padrões seguros
print("✅ Validações seguras:")
print(f"   Email 'admin@example.com': {validator.validate('admin@example.com', 'email')}")
print(f"   Email 'admin@.*.com': {validator.validate('admin@.*.com', 'email')}")
print(f"   Username 'admin': {validator.validate('admin', 'username')}")
print(f"   Username '.*': {validator.validate('.*', 'username')}")

# Busca segura
print("\n🔍 Busca segura:")
text = "This is a secret message with password=12345"
result = validator.search_safe(text, "password=.*")
print(f"   Busca por 'password=.*': {result}")

# Adicionar padrão personalizado
validator.add_custom_pattern('strong_password', r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$')
print(f"\n🔐 Senha forte: {validator.validate('StrongP@ss123', 'strong_password')}")
```

***

## 📋 **Checklists de Segurança**

### **Checklist para Desenvolvedores**

#### **Revisão de Código**

* [ ] Buscar por concatenação de strings em regex
* [ ] Verificar uso de `re.compile()` com input do usuário
* [ ] Identificar `new RegExp()` com variáveis
* [ ] Buscar por `preg_match()` com variáveis
* [ ] Verificar ausência de `re.escape()` ou `preg_quote()`

#### **Validação de Input**

* [ ] Usar whitelist de padrões predefinidos
* [ ] Escapar caracteres especiais com funções nativas
* [ ] Limitar comprimento do input antes da regex
* [ ] Validar formato antes de usar em regex

#### **Proteções Adicionais**

* [ ] Implementar timeouts em operações regex
* [ ] Configurar limites de backtracking
* [ ] Desabilitar modificadores perigosos (`/e` no PHP)
* [ ] Usar `Pattern.LITERAL` em Java

### **Checklist para Revisão de Segurança**

#### **Análise Estática**

* [ ] Executar scanners automáticos (Semgrep, Bandit)
* [ ] Verificar dependências vulneráveis
* [ ] Analisar padrões de regex em código
* [ ] Identificar funções perigosas

#### **Testes Dinâmicos**

* [ ] Testar payloads de ReDoS
* [ ] Testar bypass de validação
* [ ] Testar extração de dados
* [ ] Monitorar tempo de resposta

### **Checklist para Operações**

#### **Monitoramento**

* [ ] Monitorar uso de CPU por regex
* [ ] Alertar para timeouts frequentes
* [ ] Logging de operações regex lentas
* [ ] Detectar padrões de ataque

#### **Configuração**

* [ ] Configurar limites de backtracking
* [ ] Definir timeouts padrão
* [ ] Habilitar proteções do framework
* [ ] Atualizar regex engines

***

## 📊 **Conclusão**

```yaml
Regex Injection em Linguagens de Programação:

  🔴 Principais Vetores:
    - Concatenação de strings em regex
    - Input do usuário em re.compile()
    - Template strings em JavaScript
    - Modificador /e no PHP
    - Ausência de escape de caracteres

  🛡️ Mitigações Essenciais:
    - Usar whitelist de padrões
    - Escapar input com funções nativas
    - Implementar timeouts
    - Validar antes de compilar
    - Limitar comprimento do input

  🎯 Prioridade:
    - CRÍTICA: Validação de autenticação
    - ALTA: Processamento de input público
    - MÉDIA: Funções internas
    - BAIXA: Debug e logs
```

***

## 🔗 **Referências e Recursos**

### **Documentação Oficial**

* **Python**: [re — Regular expression operations](https://docs.python.org/3/library/re.html)
* **JavaScript**: [Regular Expressions (MDN)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)
* **Java**: [Pattern (Java SE)](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/regex/Pattern.html)
* **PHP**: [PCRE Functions](https://www.php.net/manual/en/ref.pcre.php)

### **Ferramentas de Análise**

* **Semgrep**: <https://semgrep.dev/>
* **Bandit**: <https://bandit.readthedocs.io/>
* **ESLint Security Plugin**: <https://github.com/nodesecurity/eslint-plugin-security>
* **SonarQube**: <https://www.sonarqube.org/>

### **Referências de Segurança**

* **OWASP**: [Regular Expression Denial of Service (ReDoS)](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS)
* **CWE-1333**: [Inefficient Regular Expression Complexity](https://cwe.mitre.org/data/definitions/1333.html)
* **CWE-185**: [Incorrect Regular Expression](https://cwe.mitre.org/data/definitions/185.html)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/tecnicas/linguagens-de-programacao/regex-injection.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
