Anti-Pattern: Gierige Quantifizierer in der Richtlinie "RegularExpressionProtection" verwenden

Sie lesen gerade die Dokumentation zu Apigee und Apigee Hybrid.
Apigee Edge-Dokumentation aufrufen.

Die RegularExpressionProtection-Richtlinie definiert reguläre Ausdrücke, die zur Eingabe bei Eingabeparametern oder Ablaufvariablen zur Laufzeit ausgewertet werden. Diese Richtlinie dient in der Regel zum Schutz vor Inhaltsbedrohungen wie SQL- oder JavaScript-Einschleusungen oder zum Prüfen auf fehlerhafte Anfrageparameter wie E-Mail-Adressen oder URLs.

Die regulären Ausdrücke können für Anfragepfade, Abfrageparameter, Formularparameter, Header, XML-Elemente (in einer mit XPath definierten XML-Nutzlast), JSON-Objektattribute (in einer mit JSONPath definierten JSON-Nutzlast) definiert werden.

Die folgende RegularExpressionProtection-Richtlinie schützt das Back-End vor Angriffen mit SQL-Einschleusung:

<!-- /antipatterns/examples/greedy-1.xml -->
<RegularExpressionProtection async="false" continueOnError="false" enabled="true"
  name="RegexProtection">
    <DisplayName>RegexProtection</DisplayName>
    <Properties/>
    <Source>request</Source>
    <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
    <QueryParam name="query">
      <Pattern>[\s]*(?i)((delete)|(exec)|(drop\s*table)|
        (insert)|(shutdown)|(update)|(\bor\b))</Pattern>
    </QueryParam>
</RegularExpressionProtection>

Anti-Pattern

Die Standard-Quantifizierer (*, + und ?) sind "gierig". Sie beginnen den Abgleich mit der längsten möglichen Sequenz. Wenn keine Übereinstimmung gefunden wird, schrittweise rückwärts versucht, das Muster zuzuordnen. Wenn der resultierende String, der dem Muster entspricht, sehr kurz ist, kann die Verwendung gieriger Quantifizierer mehr Zeit als nötig beanspruchen. Dies gilt insbesondere, wenn die Nutzlast groß ist (in den Dutzende oder Hunderte von KB).

Der folgende Beispielausdruck verwendet mehrere Instanzen von .*, bei denen es sich um gierige Operatoren handelt:

<Pattern>.*Exception in thread.*</Pattern>

In diesem Beispiel versucht die RegularExpressionProtection-Richtlinie zuerst, die längste mögliche Sequenz zu finden – den gesamten String. Wenn keine Übereinstimmung gefunden wird, geht die Richtlinie schrittweise zurück. Wenn der übereinstimmende String nahe am Anfang oder in der Mitte der Nutzlast liegt, kann die Verwendung eines gierigen Quantifizierers wie .* viel mehr Zeit und Verarbeitungsleistung als träge Quantifizierer wie .*? oder (weniger gebräuchlich) possessive Quantifizierer wie .*+ benötigen.

Zögerliche Quantifizierer (wie X*?, X+?, X??) beginnen zuerst mit dem Abgleich eines einzelnen Zeichens vom Anfang der Nutzlast und fügen dann schrittweise Zeichen hinzu. Possessive Quantifizierer (wie X?+, X*+, X++) versuchen nur einmal, die gesamte Nutzlast abzugleichen.

Betrachten Sie für das obige Muster den folgenden Beispieltext:

Hello this is a sample text with Exception in thread
with lot of text after the Exception text.

Die Verwendung des gierigen .* ist in diesem Fall nicht effizient. Das Muster .*Exception in thread.* erfordert 141 Schritte. Wenn Sie stattdessen das Muster .*?Exception in thread.* verwendet haben, das einen quantitativen Quantifizierer verwendet, beträgt das Ergebnis nur 55 Schritte.

Auswirkungen

Die Verwendung gieriger Quantifizierer wie Platzhalter (*) mit der RegularExpressionProtection-Richtlinie kann zu Folgendem führen:

  • Eine Erhöhung der Gesamtlatenz für API-Anfragen für eine moderate Nutzlast (bis zu 1 MB)
  • Längere Zeit bei der Ausführung der RegularExpressionProtection-Richtlinie
  • API-Anfragen mit großen Nutzlasten (mehr als 1 MB), die mit 504 Gateway-Zeitüberschreitungsfehlern fehlschlagen, wenn der vordefinierte Zeitüberschreitungszeitraum auf dem Apigee-Router abgelaufen ist
  • Hohe CPU-Auslastung bei Nachrichtenverarbeitern aufgrund einer hohen Verarbeitungsmenge, die sich auch auf andere API-Anfragen auswirken kann

Best Practice

  • Vermeiden Sie in der Regel die Verwendung von gierigen Quantifizierern wie .* mit der RegularExpressionProtection-Richtlinie. Verwenden Sie nach Möglichkeit stattdessen träge Quantifizierer wie .*? oder sinnvolle Quantifizierer wie .*+ (seltener).

Weitere Informationen