Aikido

Schutz vor langsamen regulären Ausdrücken: Verhinderung von ReDoS-Angriffen

Lesbarkeit

Regel
Wache gegen langsam reguläre Ausdrücke.
Reguläre Ausdrücke mit verschachtelten Quantoren oder 
mehrdeutigen Mustern können verursachen. katastrophale 
Backtracking und Leistung Probleme.
Unterstützte Sprachen: 45+

Einführung

Reguläre Ausdrücke können Ihre Anwendung mit der richtigen Eingabe für Sekunden oder Minuten zum Stillstand bringen. Katastrophales Backtracking tritt auf, wenn Regex-Engines exponentiell ansteigende Pfade erkunden, während sie versuchen, ein Muster zu finden. Ein Regex wie (a+)+b braucht Mikrosekunden, um gültige Eingaben zu erkennen, kann aber Stunden brauchen, um eine Folge von a's ohne nachgestelltes b zurückzuweisen. Angreifer nutzen dies durch ReDoS-Angriffe (Regular Expression Denial of Service) aus, indem sie manipulierte Eingaben senden, die Ihre Regex-Engine zu 100 % CPU-Leistung bringen, bis es zu Anfrage-Timeouts kommt oder der Prozess abstürzt.

Warum das wichtig ist

Auswirkungen auf die Sicherheit (ReDoS-Angriffe): Ein Angreifer kann Ihre Anwendung mit einer einzigen Anfrage mit manipulierten Eingaben lahmlegen. E-Mail-Validierung und URL-Parsing-Muster sind häufige Ziele. Im Gegensatz zu herkömmlichen DoS-Angriffen, die Bandbreite erfordern, benötigt ReDoS nur winzige Nutzdaten.

Leistungsverschlechterung: Normale Benutzereingaben können ein katastrophales Backtracking auslösen, wodurch die Antwortzeiten von Millisekunden auf Sekunden ansteigen. Dies führt zu unvorhersehbaren Latenzzeiten, die schwer zu beheben sind, da sie nur bei bestimmten Eingabemustern auftreten.

Vorfälle in der Produktion: Anfällige Regex blockiert die Ereignisschleife in Node.js oder verbraucht Thread-Pool-Ressourcen. Wenn sich die Anfragen häufen, steigt der Speicherbedarf und das System reagiert nicht mehr. Bei Microservices führt eine anfällige Regex zu kaskadenartigen Ausfällen bei abhängigen Diensten.

Schwierigkeit bei der Erkennung: Muster, die beim Testen mit kurzen Eingaben gut funktionieren, werden bei längeren Eingaben exponentiell langsam. Die Schwachstelle bleibt oft bis zur Produktion unbemerkt und erfordert einen Notfalleinsatz bei einem aktiven Vorfall.

Code-Beispiele

❌ Nicht konform:

function validateEmail(email) {
    const regex = /^([a-zA-Z0-9_\-\.]+)+@([a-zA-Z0-9_\-\.]+)+\.([a-zA-Z]{2,5})$/;
    return regex.test(email);
}

function extractURLs(text) {
    const regex = /(https?:\/\/)?([\w\-])+\.(\w+)+([\w\-\.,@?^=%&:/~\+#]*)+/g;
    return text.match(regex);
}

Warum es unsicher ist: Die verschachtelten Quantoren ([a-zA-Z0-9_\\-\\.]+)+ zu exponentiellem Backtracking führen. Für eine E-Mail wie aaaaaaaaaaaaaaaaaaaaaaaaa!probiert die Regex-Engine unzählige Kombinationen aus, bevor sie scheitert. Die URL-Regex hat mehrere verschachtelte Quantifizierer, die das Problem verschlimmern, so dass sie mit Eingaben wie langen Zeichenfolgen ohne die erwartete Struktur trivial ausgenutzt werden kann.

✅ Konform:

function validateEmail(email) {
    const regex = /^[a-zA-Z0-9_\-\.]+@[a-zA-Z0-9_\-\.]+\.[a-zA-Z]{2,5}$/;
    return regex.test(email);
}

function extractURLs(text) {
    const regex = /https?:\/\/[\w\-]+\.[\w\-]+(?:[\w\-\.,@?^=%&:/~\+#]*)?/g;
    return text.match(regex);
}

Warum es sicher ist: Das Entfernen von verschachtelten Quantoren verhindert katastrophales Backtracking. Einzelne Quantoren wie [a-zA-Z0-9_\-\.]+ werden in linearer Zeit ausgeführt. Das URL-Muster verwendet nicht-erfassende Gruppen mit optionalem Suffix (?:...)? anstelle von verschachtelten Wiederholungen, was eine vorhersehbare Leistung unabhängig von Eingabelänge oder Inhalt gewährleistet.

Schlussfolgerung

Die Leistung regulärer Ausdrücke ist ein Sicherheitsaspekt, nicht nur eine Optimierung. Überprüfen Sie alle Regex-Muster auf verschachtelte Quantoren, sich überschneidende Zeichenklassen in Wiederholungsgruppen und mehrdeutige Alternativen. Testen Sie Regex-Muster mit pathologischen Eingaben (lange Zeichenketten mit gültigen Zeichen, gefolgt von ungültigen Endungen), um katastrophales Backtracking vor dem Einsatz zu erkennen. Ersetzen Sie, wenn möglich, komplexe Regex durch String-Parsing-Funktionen, die vorhersehbare Leistungsmerkmale aufweisen.

FAQs

Haben Sie Fragen?

Welche Muster führen zu katastrophalem Backtracking?

Häufige Übeltäter sind verschachtelte Quantoren wie (a+)+, (a*)*, oder (a+)*b. Alternation mit sich überschneidenden Mustern wie (a|a)* oder (a|ab)*. Wiederholungen mit optionalen Komponenten wie (a?)+. Jedes Muster, bei dem die Regex-Engine dieselbe Teilzeichenkette auf mehrere Arten finden kann, erzeugt exponentiellen Suchraum. Achten Sie auf Quantoren (+, *, {n,m}) innerhalb von Gruppen, die selbst quantifiziert sind.

Wie kann ich testen, ob meine Regex für ReDoS anfällig ist?

Verwenden Sie Online-Tools wie regex101.com, die Ausführungsschritte anzeigen und vor katastrophalem Backtracking warnen. Erstellen Sie Testeingaben mit langen Zeichenketten aus gültigen Zeichen, gefolgt von Zeichen, die ein Backtracking erzwingen. Testen Sie für das Muster /^(a+)+b$/ mit "aaaaaaaaaaaaaaaaa!" (30+ a's, kein b). Wenn die Ausführung mehr als Millisekunden dauert, ist die Regex angreifbar. Implementieren Sie Timeouts bei Regex-Operationen in der Produktion, um sich abzusichern.

Was ist der Unterschied zwischen katastrophalem und linearem Backtracking?

Lineares Backtracking tritt auf, wenn der Regex Alternativen nacheinander ausprobiert, aber frühere Entscheidungen nicht neu bewertet. Die Arbeit wächst linear mit der Größe der Eingabe. Zu katastrophalem Backtracking kommt es, wenn verschachtelte Quantoren die Engine zwingen, exponentiell viele Kombinationen auszuprobieren. Bei Eingaben der Länge n kann die Ausführungszeit O(2^n) oder noch schlechter sein. Der Unterschied liegt zwischen Millisekunden und Minuten für bescheidene Eingabegrößen.

Kann ich Lookaheads und Lookbehinds sicher verwenden?

Lookaheads (?=...) and lookbehinds (?<=...) themselves don't cause catastrophic backtracking, but they can hide vulnerable patterns. A lookahead containing (a+)+ is still vulnerable. Use lookarounds for their intended purpose (assertions without consuming characters), not as a workaround for complex matching. Keep the patterns inside lookarounds simple and test them thoroughly.

Gibt es Regex-Engines, die katastrophales Backtracking verhindern?

RE2 (von Google verwendet) garantiert eine lineare Zeitausführung, indem es Backtracking vollständig verbietet. Es unterstützt nicht alle Funktionen (Backreferences, Lookarounds), verhindert aber ReDoS vollständig. Für kritische Sicherheitsprüfungen sollten Sie RE2-Bindings oder ähnliche Engines verwenden. Für JavaScript gibt es keine eingebaute Alternative, daher sind Pattern-Design und Timeouts Ihre primären Schutzmaßnahmen.

Sollte ich allen Regex-Operationen Zeitüberschreitungen hinzufügen?

Für nicht vertrauenswürdige Eingaben (vom Benutzer bereitgestellte Daten, externe API-Antworten), ja. Setzen Sie vernünftige Timeouts wie 100-500ms je nach erwarteter Komplexität. In Node.js können Sie regex.test() nicht direkt mit einem Timeout versehen, aber Sie können die Eingabelänge zuerst validieren oder regex in einem Worker-Thread mit Timeout ausführen. Weisen Sie Eingaben zurück, die eine angemessene Länge überschreiten, bevor Sie den Regex-Abgleich versuchen.

Wie repariere ich ein bestehendes anfälliges Regex-Muster?

Bestimmen Sie zunächst, ob Sie überhaupt Regex benötigen. Viele Überprüfungsaufgaben lassen sich mit String-Methoden wie includes(), startsWith() oder split() einfacher lösen. Wenn Regex notwendig ist, eliminieren Sie verschachtelte Quantoren, indem Sie das Muster abflachen. Ersetzen Sie (a+)+ durch a+. Verwenden Sie atomare Gruppen oder possessive Quantoren, wenn Ihre Regex-Engine sie unterstützt. Bei komplexen Mustern sollten Sie erwägen, die Eingabe in mehreren Durchgängen mit einfacheren Regex- oder String-Operationen zu parsen.

Starten Sie kostenlos

Sichern Sie Ihren Code, Cloud und die Laufzeit in einem zentralen System.
Finden und beheben Sie Schwachstellen schnell  automatisch.

Keine Kreditkarte erforderlich | Scanergebnisse in 32 Sekunden.