Skip to main content

Snyking In – Exploit einer Regular-Expression-DoS-Schwachstelle im Paket ms

Artikel von
Snyking in small

13. März 2019

0 Min. Lesezeit

Willkommen zu einer weiteren Ausgabe unserer Exploit-Reihe Snyking In! Letztes Mal haben wir uns einen Exploit einer Directory-Traversal-Schwachstelle in der Bibliothek st angesehen. In dieser Folge geht es um die Regular-Expression-DoS-Schwachstelle. Wir zeigen, wie sie ausgenutzt werden kann und welche Risiken sie für Ihre Daten und Systeme birgt.

Außerdem zeigen wir Ihnen, wie Sie diese Art von Schwachstelle in Ihrer Anwendung finden und beheben können. Doch genug der Vorrede: Hier ist das Exploit-Video, gefolgt von weiteren Informationen zur Regular-Expression-DoS-Schwachstelle.

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

Regular-Expression-DoS

Denial of Service (DoS) bezeichnet eine Gruppe von Angriffen, die alle darauf abzielen, ein System für seine legitimen Nutzerinnen und Nutzer unzugänglich zu machen. Es gibt viele Arten von DoS-Angriffen: von dem Versuch, die Netzwerkverbindungen eines Systems durch eine große Menge an Datenverkehr von vielen Rechnern zu überlasten (ein verteilter Denial-of-Service-Angriff, DDoS), bis hin zum Senden speziell gestalteter Anfragen, die ein System zum Absturz bringen oder unverhältnismäßig viel Zeit für die Verarbeitung beanspruchen.

Regular Expression Denial of Service (ReDoS) ist eine Form des Denial-of-Service-Angriffs. Reguläre Ausdrücke sind äußerst leistungsfähig, aber nicht besonders intuitiv. Dadurch können Angreifer Ihre Website letztlich leicht lahmlegen.

Der kürzlich von Snyk veröffentlichte Bericht zur Sicherheit von Open Source zeigt, dass die Zahl der Meldungen zu Regular-Expression-DoS-Schwachstellen allein im vergangenen Jahr um 143 % gestiegen ist.

Liniendiagramm mit dem Titel „Meldungen zu Regular Expression Denial of Service (ReDoS) nehmen zu“: Die Zahl steigt von 14 im Jahr 2016 auf 30 im Jahr 2017 und 72 im

Katastrophales Backtracking

Sehen wir uns den folgenden regulären Ausdruck an:

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

Dieser reguläre Ausdruck bewirkt Folgendes:

  • A Die Zeichenfolge muss mit dem Buchstaben A beginnen.

  • (B|C+)+ Auf den Buchstaben A muss entweder der Buchstabe B oder eine beliebige Anzahl von Vorkommen des Buchstabens C folgen (das + steht für ein oder mehrere Vorkommen). Das + am Ende dieses Abschnitts gibt an, dass dieser Abschnitt ein oder mehrere Male vorkommen kann.

  • D Zum Schluss stellen wir sicher, dass dieser Abschnitt der Zeichenfolge mit einem D endet.

Der Ausdruck würde beispielsweise auf ABBD, ABCCCCD, ABCBCCCD und ACCCCCD passen. In den meisten Fällen braucht eine Regex-Engine nicht lange, um eine Übereinstimmung zu finden:

$ 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

Der gesamte Test mit einer 30 Zeichen langen Zeichenfolge dauert etwa 52 ms. Bei einer ungültigen Zeichenfolge dauert der Test jedoch fast zwei Sekunden – mehr als zehnmal so lange wie bei einer gültigen Zeichenfolge. Dieser große Unterschied ist auf die Art zurückzuführen, wie reguläre Ausdrücke ausgewertet werden.

Die meisten Regex-Engines funktionieren sehr ähnlich (mit geringfügigen Unterschieden). Die Engine wählt den ersten möglichen Weg, um das aktuelle Zeichen zu akzeptieren, und fährt mit dem nächsten fort. Kann sie das nächste Zeichen nicht zuordnen, geht sie zurück und prüft, ob es eine andere Möglichkeit gab, das vorherige Zeichen zu verarbeiten. Wenn sie sich zu weit in dieses Labyrinth vorwagt und erst dann feststellt, dass die Zeichenfolge letztlich nicht passt, kann die Zahl der Backtracking-Schritte sehr groß werden – insbesondere, wenn sich für viele Zeichen mehrere gültige Regex-Pfade anbieten. Das Ergebnis ist das sogenannte katastrophale Backtracking.

Der ms-Exploit

Der folgende Befehl fügt der Todo-Anwendung Snyk Goof einen Todo-Eintrag hinzu. Der Teil in 20 minutes im Inhaltstext wird von der Regex-Engine als Zeitangabe erkannt. Die Anwendungslogik könnte diese Angabe beispielsweise dazu verwenden, Erinnerungen oder Warnmeldungen zu erstellen.

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

Wir können versuchen, die Länge des Todo-Eintrags wie folgt mit Brute-Force zu ermitteln. Der Befehl gibt 60000 5s als Minutenzahl aus. Da das Muster jedoch weiterhin passt, erfolgt die Rückgabe sehr schnell.

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

Um einen Denial-of-Service-Angriff auszulösen, müssen wir eine Zeichenfolge übergeben, die katastrophales Backtracking verursacht. Dazu ist unter anderem eine lange Eingabe wie im vorherigen Beispiel nötig. Gleichzeitig müssen wir sicherstellen, dass die Regex-Engine das Muster nie findet und deshalb alle Möglichkeiten durchgeht, bevor sie abbricht. Das führt zu der Verzögerung oder dem Denial of Service, den wir erreichen wollen. Dafür können wir den Text minutes in unserem Inhaltstext beispielsweise in minutea ändern – ein Muster, das die Regex-Engine nicht erkennt. Der folgende Befehl zum Eintragen eines Todo-Elements verursacht einen Denial of Service von etwa 10 bis 15 Sekunden. Übergeben wir 600000 5s, warten wir auf dem Server bis zum Ende des Tages, bis die Anfrage abgeschlossen ist.

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

Um Ihre Anwendung auf Schwachstellen in Bibliotheken von Drittanbietern wie ms zu testen, probieren Sie Snyk kostenlos aus.

Starten Sie mit Capture-the-Flag

Erfahren Sie in unserem virtuellen On-Demand-Workshop für Einsteiger, wie Sie Capture-the-Flag-Challenges lösen.