Denial-of-Service-Bedenken
Das häufigste Problem bei Regexen ist ein Denial-of-Service-Angriff durch pathologische Muster, die exponentiell oder sogar überexponentiell verlaufen! - und so scheint es ewig zu dauern, bis es gelöst ist. Diese werden möglicherweise nur bei bestimmten Eingabedaten angezeigt, aber im Allgemeinen kann eine erstellt werden, bei der dies keine Rolle spielt.
Welche dies sind, hängt etwas davon ab, wie intelligent der von Ihnen verwendete Regex-Compiler ist, da einige davon während der Kompilierungszeit erkannt werden können. Regex-Compiler, die eine Rekursion implementieren, verfügen normalerweise über einen integrierten Rekursionstiefenzähler zur Überprüfung der Nichtprogression.
Russ Cox 'exzellentes Papier von 2007 über das Abgleichen regulärer Ausdrücke kann einfach und schnell sein (ist aber in Java, Perl, PHP, Python, Ruby usw. langsam) und beschreibt Möglichkeiten, wie die meisten modernen NFAs, die alle von Henry Spencers Code abgeleitet zu sein scheinen leiden unter starken Leistungseinbußen, aber wo ein NFA im Thompson-Stil keine derartigen Probleme hat.
Wenn Sie nur Muster zulassen, die von DFAs gelöst werden können, können Sie sie als solche kompilieren, und sie werden schneller ausgeführt, möglicherweise viel schneller. Es braucht jedoch Zeit , um dies zu tun. Das Cox-Papier erwähnt diesen Ansatz und die damit verbundenen Probleme. Es kommt alles auf einen klassischen Zeit-Raum-Kompromiss an.
Mit einem DFA verbringen Sie mehr Zeit damit, ihn zu erstellen (und mehr Zustände zuzuweisen), während Sie mit einem NFA mehr Zeit damit verbringen, ihn auszuführen, da es sich um mehrere Zustände gleichzeitig handeln kann und das Zurückverfolgen Ihr Mittagessen und Ihre CPU verschlingen kann.
Denial-of-Service-Lösungen
Der wahrscheinlich vernünftigste Weg, um diese Muster anzugehen, die am Ende eines Rennens mit dem Hitzetod des Universums stehen, besteht darin, sie mit einem Timer zu versehen, der effektiv eine maximale Zeitspanne für ihre Ausführung festlegt. Normalerweise ist dies viel, viel weniger als das Standardzeitlimit, das die meisten HTTP-Server bieten.
Es gibt verschiedene Möglichkeiten, diese zu implementieren, angefangen von einer einfachen alarm(N)
auf C-Ebene bis hin zu einer Art try {}
Blockierung der Ausnahmen vom Typ "Catch-Alarm", bis hin zum Laichen eines neuen Threads, der speziell mit einer integrierten Zeitbeschränkung erstellt wurde.
Code-Beschriftungen
In Regex-Sprachen, die Code-Callouts zulassen, sollte ein Mechanismus bereitgestellt werden, mit dem diese für die zu kompilierende Zeichenfolge zugelassen oder nicht zugelassen werden können. Auch wenn Code-Beschriftungen nur in der von Ihnen verwendeten Sprache codieren sollen, sollten Sie sie einschränken. Sie müssen nicht in der Lage sein, externen Code aufzurufen, obwohl Sie, wenn sie können, viel größere Probleme haben.
In Perl können beispielsweise keine Code-Beschriftungen in regulären Ausdrücken aus Zeichenfolgeninterpolation erstellt werden (wie dies bei der Kompilierung zur Laufzeit der Fall wäre), es sei denn, das spezielle Pragma mit lexikalischem Gültigkeitsbereich ist use re "eval";
im aktuellen Bereich aktiv.
Auf diese Weise kann sich niemand in ein Code-Callout einschleichen rm -rf *
, um beispielsweise Systemprogramme auszuführen . Da Code-Callouts so sicherheitsrelevant sind, deaktiviert Perl sie standardmäßig für alle interpolierten Zeichenfolgen, und Sie müssen alles tun, um sie wieder zu aktivieren.
Benutzerdefiniert \ P {Eigenschaften}
Es bleibt eine mehr sicherheitsrelevante Fragen im Zusammenhang mit Unicode-Stil Eigenschaften - wie \pM
, \p{Pd}
, \p{Pattern_Syntax}
oder \p{Script=Greek}
- das kann in einigen Regex Compiler gibt , die Unterstützung , die Notation.
Das Problem ist, dass in einigen von diesen die möglichen Eigenschaften vom Benutzer erweiterbar sind. Das bedeutet, dass Sie benutzerdefinierte Eigenschaften haben können, die tatsächliche Code-Beschriftungen für benannte Funktionen in einem bestimmten Namespace wie \p{GoodChars}
oder sind \p{Class::Good_Characters}
. Es könnte sich lohnen, einen Blick darauf zu werfen, wie Ihre Sprache damit umgeht.
Sandboxing
In Perl würde ein Sandkastenfach über das Safe
Modul die Kontrolle über die Sichtbarkeit von Namespaces ermöglichen. Andere Sprachen bieten ähnliche Sandbox-Technologien an. Wenn solche Geräte verfügbar sind, sollten Sie sie untersuchen, da sie speziell für die eingeschränkte Ausführung von nicht vertrauenswürdigem Code entwickelt wurden.