Antipattern: usa quantificatori greedy nel criterio RegularExpressionProtection

Stai visualizzando la documentazione relativa a Apigee e Apigee ibrido.
Visualizza Documentazione di Apigee Edge.

Il criterio RegularExpressionProtection definisce le espressioni regolari valutate in base il tempo di esecuzione sui parametri di input o sulle variabili di flusso. In genere utilizzi questo criterio per proteggerti da minacce nei contenuti come SQL injection o JavaScript oppure per verificare la presenza di parametri di richiesta non corretti come indirizzi email o URL.

È possibile definire espressioni regolari per percorsi di richiesta, parametri di ricerca, parametri intestazioni, elementi XML (in un payload XML definito utilizzando XPath), attributi degli oggetti JSON (in un file JSON payload definito utilizzando JSONPath).

Il seguente criterio RegularExpressionProtection protegge il backend da SQL attacchi con iniezione di codice:

<!-- /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>

Antipattern

I quantificatori predefiniti (*, + e ?) sono ingordi naturale: iniziano a corrispondere alla sequenza più lunga possibile. Se non trova corrispondenze, torna gradualmente indietro per cercare di adattarlo allo schema. Se la stringa risultante corrispondente al pattern è molto breve, l'uso di quantificatori avidi può richiedere più tempo del necessario. In particolare true se il payload è di grandi dimensioni (in decine o centinaia di kB).

La seguente espressione di esempio utilizza più istanze di .*, che sono greedy operatori:

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

In questo esempio, il criterio RegularExpressionProtection tenta innanzitutto di trovare la corrispondenza più lunga possibile sequenza: l'intera stringa. Se non viene trovata alcuna corrispondenza, la norma torna indietro nel tempo gradualmente. Se la stringa corrispondente è vicina all'inizio o alla metà del payload, l'uso di un quantificatore greedy come .* può richiedere molto più tempo e potenza di elaborazione rispetto ai riluttanti qualificatori come .*? o (meno comunemente) quantificatori possessivi come .*+.

I quantificatori riluttanti (come X*?, X+?, X??) iniziano provando per trovare una corrispondenza con un singolo carattere dall'inizio del payload e aggiungere gradualmente i caratteri. I quantificatori propositivi (come X?+, X*+, X++) cercano di trovare una corrispondenza con l'intero payload solo una volta.

Dato il seguente testo di esempio per il pattern riportato sopra:

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

In questo caso, l'utilizzo dello standard .* greedy non è efficace. Lo schema .*Exception in thread.* richiede 141 passi per abbinare. Se hai utilizzato lo schema .*?Exception in thread.* (che utilizza un quantificatore riluttante), il risultato essere di soli 55 passi.

Impatto

Utilizzo di quantificatori greedy come caratteri jolly (*) con Il criterio RegularExpressionProtection può causare:

  • Un aumento della latenza complessiva per le richieste API per una dimensione del payload moderata (fino a 1 MB)
  • Tempi più lunghi per completare l'esecuzione del criterio RegularExpressionProtection
  • Richieste API con payload di grandi dimensioni (>1 MB) che non superano il controllo e restituiscono 504 errori di timeout del gateway se scade il periodo di timeout predefinito sul router Apigee
  • Elevato utilizzo della CPU nei processori di messaggi a causa dell'elevata quantità di elaborazione che può ulteriormente influire su altre richieste API

Best practice

  • Evita di utilizzare quantificatori avidi come .* nelle espressioni regolari con la macro Criterio RegularExpressionProtection. Usa invece quantificatori riluttanti come .*? o quantificatori possessivi come .*+ (meno comunemente) ovunque possibile.

Per approfondire