Proteggere l'input dell'utente di espressioni regolari dagli attacchi


9

Sono a conoscenza di Denial of Service (ReDoS) di espressioni regolari. Esiste un modo ragionevole per consentire agli utenti di creare regex personalizzate garantendo al contempo di non presentare un pattern esponenzialmente lento?


Mancano dettagli. Piattaforma, utilizzo, ecc.
whatsisname

8
Invece di cercare di evitare che l'utente presenti una regex errata, forse una soluzione in cui dopo un certo periodo di tempo si annulla l'esecuzione?
Samuel,

Risposte:


8

Il problema con le espressioni regolari non è la regex stessa, ma che il motore regex ha tutti i tipi di funzionalità "convenienti" come il backtracking. Pertanto, l'utilizzo di un motore regex senza queste funzionalità evita.

Le espressioni regolari del concetto di informatica possono sempre essere abbinate in tempo lineare dopo essere state compilate in una macchina a stati finiti. Quindi un motore regex basato su macchine a stati non può essere usato per ReDoS. Tuttavia, le macchine a stati necessarie possono diventare piuttosto grandi in esempi patologici. Ma limitare la memoria disponibile tende ad essere più facile che limitare il tempo di calcolo disponibile.

Il motore RE2 è stato sviluppato appositamente per gestire regex non attendibili ed è stato progettato per l'esecuzione a tempo lineare.

Un'altra alternativa è assemblare te stesso le regex da una notazione semplificata. Ad esempio, potresti consentire agli utenti di utilizzare modelli glob (come *.txt). È quindi possibile analizzarlo in un modo che impedisce il backtracking, ad esempio impedendo l'annidamento e utilizzando solo quantificatori avidi. Per molti casi d'uso, una notazione di modello semplificata è completamente sufficiente.


11

Analizzare un'espressione regolare per vedere se sarà lenta o no, senza che l'analisi diventi lenta , equivale a risolvere il problema di arresto. In altre parole, non è possibile trovare una soluzione corretta e completa.

È possibile, naturalmente, trovare una soluzione che sia corretto e in completa. Ad esempio, è possibile lavorare con una lista bianca restrittiva di funzionalità sicure da usare (ad es. Classi di caratteri sì, ripetizione no ...). Ciò ti consentirebbe di passare molte regex acritiche, rifiutare tutte quelle critiche e (erroneamente) rifiutare alcune che sono a posto, ma troppo complicate per dimostrarsi automaticamente sicure.


3
Hai una citazione per la tua prima affermazione? Sarei interessato a vedere una tale prova. I regex non sono completi di Turing, quindi il problema di arresto potrebbe non essere applicabile.
Sebastian Redl,

3
@SebastianRedl È vero che, a rigor di termini, le espressioni regolari non sono complete di Turing, ma tutte le librerie regex di uso comune hanno estensioni che non le rendono più regolari. Limitare i tuoi utenti a espressioni letteralmente regolari potrebbe, in effetti, essere una buona soluzione per questa situazione.
Kilian Foth,

2
@KilianFoth: IIRC, anche le vere espressioni regolari (nel senso CompSci della parola) possono richiedere una quantità esponenziale di backtracking. Ma poiché non sono completi di Turing, per ogni data regex è teoricamente possibile stabilire questo limite superiore. Tuttavia, ciò lascia aperti due problemi: determinare automaticamente il limite superiore è un'attività non banale e il risultato può dare risultati irragionevolmente alti (come in, un limite superiore molto più alto del tempo previsto ).
Salterio,

@msalters qualsiasi vera espressione regolare è meccanicamente convertibile in un automa a stati finiti deterministico, cioè è sempre possibile abbinare l'espressione senza alcun backtracking. La tua FSA potrebbe diventare irragionevolmente grande, ovviamente, ma ciò suggerisce che un limite al numero di stati nella FSA generata è una soluzione sufficiente per prevenire l'attacco in questione.
Jules,

1

Come autore del re parser per il progetto lazzaro, direi che non ci sono modi per capire per una determinata espressione regolare quali risorse consumerà in un dato testo.

Senza spendere le stesse risorse intendo (almeno nel significato di big-O).

Quindi l'approccio migliore: esegui re parser in thread separato e uccidilo dopo il timeout.


0

Oltre alle altre risposte, una soluzione potrebbe anche essere quella di eseguire il rollup della propria libreria regex, che consente la strumentazione delle prestazioni durante l'esecuzione e quindi fornisce i mezzi per terminare l'esecuzione a metà strada se vengono soddisfatti alcuni criteri.

Allo stesso modo, potresti eseguire le regex su un altro thread e uccidere i thread se impiegano troppo tempo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.