Per ogni regex 'malvagio', esiste un'alternativa non malvagia o il diavolo è nella grammatica?


16

Apparentemente, ReDos attacchi sfruttano le caratteristiche di alcune espressioni regolari (altrimenti utili) ... causando essenzialmente un'esplosione di possibili percorsi attraverso il grafico definito dall'NFA.

È possibile evitare tali problemi scrivendo una regex "non malvagia" equivalente? In caso contrario (quindi, la grammatica non può essere gestita nello spazio / tempo pratico da un NFA), quali approcci di analisi sarebbero migliori? Perché?


Se sono riuscito a usare un linguaggio tecnico preciso, è un incidente. Per favore, sminuisci le risposte per un non accademico :-)
David Bullock

1
In realtà sto solo cercando di trovare un modo pratico per evitare di essere ReDos , e questa domanda è emersa .
David Bullock,

Per riformulare la tua domanda (?): Ogni linguaggio regolare ha un'espressione regolare la cui lunghezza è limitata da un polinomio nel numero di stati del suo NFA minimo?
A.Schulz,

1
@ A.Schulz. Non credo sia questa la domanda. Non è così che funzionano gli attacchi ReDos. In un attacco ReDos, regexp è codificato nel codice sorgente del programma e viene fornito dallo sviluppatore, che si presume essere attendibile. Quindi, l'avversario arriva a fornire una stringa di input, che il programma corrisponde al regexp. Se l'avversario riesce a trovare una stringa di input che fa funzionare il matcher per un tempo davvero lungo, l'avversario vince. Quindi, siamo preoccupati per gli input contraddittori, non per le espressioni regolari contraddittorie. (continua)
DW

Di conseguenza, penso che la domanda sia invece: ogni linguaggio regolare ha un'espressione regolare tale che la corrispondenza di a n-la stringa di caratteri contro quell'espressione regolare accetta O(f(n)) tempo, dove f(n) è una funzione di crescita non troppo rapida di n(diciamo, polinomiale o qualcosa del genere)? [Per inciso, questa riformulazione chiarisce che la risposta dipenderà dall'algoritmo usato per la corrispondenza ... come menziono nella mia risposta.] La dimensione dell'espressione regolare in funzione della dimensione della NFA minima non lo fa importa davvero qui.
DW

Risposte:


14

Dipende dal fatto che tu abbia un'espressione regolare o una regexp: le regexps sono malvagie, ma le espressioni regolari sono una cosa di bellezza e non trasformeranno mai il male in te.

Per regexp intendo un'espressione regolare moderna: vale a dire un'espressione regolare con caratteristiche moderne aggiuntive come i riferimenti indietro - ad esempio, un'espressione regolare compatibile con Perl. Ciò è più potente di un'espressione regolare classica da un manuale di teoria dei linguaggi / automi formali, poiché le espressioni regolari classiche non consentono riferimenti indietro, lookahind, lookbehind e così via.

For a classical regular expression, if you have a good implementation for the matcher, then no regular expression is too evil. In particular, a standard algorithm for matching is to convert the regular expression to a NFA and then executing the NFA on an input string. For this algorithm, the worst-case running time to test a n-character string is O(n), when the regular expression is fixed. This means that the running time can't explode too rapidly. There is no string that will cause an exponential increase in running time. Thus, if you're using a matcher that uses this algorithm, no classical regular expression will be evil.

This does depend on the implementation of the regular expression matcher. If you have a naive or poor implementation of the matcher, then matching could take exponential time; there are certainly algorithms with that property. But the best answer to that is probably not to change the regular expression; it's probably better to pick a better matcher, if you are concerned about denial-of-service attacks.

In confronto, alcune regexps moderne sono inevitabilmente malvagie. Se hai una regexp moderna, la corrispondenza può richiedere tempo esponenziale. In particolare, regexps con backreferences possono riconoscere le lingue NP-hard. Di conseguenza, sotto ipotesi plausibili, esiste una classe di regexps malvagi in cui il test per una partita richiede tempo esponenziale. Pertanto, alcune regexp moderne sono inevitabilmente malvagie: non esiste un modo fattibile per trovare una regexp equivalente che non causi lo scoppio esponenziale del tempo di esecuzione.

(Un simile equivalente potrebbe esistere e potrebbe anche essere reperibile in teoria, ma in base a ipotesi plausibili, trovare la regexp equivalente richiederà tempo esponenziale, il che non è fattibile in pratica. Se avessi una procedura sistematica per trovare la regexp equivalente in tempo polinomiale , quindi potresti risolvere il problema NP-difficile in tempo polinomiale, dimostrando che P = NP. Non fa molto bene che esista una regexp equivalente se non c'è modo di trovarlo effettivamente nella tua vita.)


Contesto e fonti:


Isn't it easier to find a non-evil alternative by splitting up the regex into multiple smaller regexes and use them in combination?
inf3rno

1

This answer will take a more overarching view of this unusual crosscutting situation, where complexity theory is applicable to cybersecurity and the example contains some of the significant nuance/ subtlety that can occur in this area. This is essentially similar to an "injection attack" where certain unexpected inputs cause pathological behavior either crashing a system or causing it to take an abnormally long time.

Wikipedia has 15 categories of Denial of Service attacks and this attack falls into "application level floods" in that list. Another somewhat similar example is an attack that fills up application logs.

Una correzione per gli attacchi di iniezione è "pulire l'input". Il progettista dell'applicazione può rivalutare se è necessario compilare regexps arbitrari forniti da un utente potenzialmente dannoso. Semplicemente rimuovere le espressioni nidificate nella regexp o qualche altra limitazione simile sarebbe probabilmente sufficiente per evitare questo attacco. Sebbene siano intrinseci a molti software moderni, è possibile fornire grandi quantità di funzionalità senza valutare le espressioni regolari. Il contesto è importante, alcune applicazioni non richiedono tale sicurezza.

Another approach to improve fault tolerance/ resilience that is applicable here are timeouts specified at different levels of the software stack/ hierarchy. The idea would be to specify a time/ cpu or instruction limit on a "average" regular expression evaluation and terminate early if its exceeded. They can be implemented with custom solutions but not very much software or programming languages have built-in timeouts or frameworks for this purpose.

Here is a nice example of the use of timeouts to improve fault tolerance and shows a high-level design/ architecture/ pov to mitigate such issues: Fault Tolerance in a High Volume, Distributed System / Netflix. It has nothing specifically connected to regular expressions but thats the point here: virtually any/ all application level logic can fit into this framework or something similar.

This article points out how backtracking in particular can lead to slow regexp matching. Regexps have many different features and one could attempt to evaluate which ones lead to worst case behaviors.

Here is a nice scientific survey of this particular topic with static analysis solution(s) proposed:

  • Analisi statica per runtime esponenziale di espressione regolare tramite logica substrutturale / Rathnayake, Thielecke

    La corrispondenza delle espressioni regolari mediante backtracking può avere un runtime esponenziale, portando a un attacco di complessità algoritmica noto come REDoS nella documentazione sulla sicurezza dei sistemi. In questo articolo, ci basiamo su un'analisi statica pubblicata di recente che rileva se una determinata espressione regolare può avere un runtime esponenziale per alcuni input. Costruiamo sistematicamente un'analisi più accurata formando poteri e prodotti delle relazioni di transizione e riducendo così il problema REDoS alla raggiungibilità. La correttezza dell'analisi è dimostrata usando un calcolo sostruttivo degli alberi di ricerca, in cui la ramificazione dell'albero che causa l'esplosione esponenziale è caratterizzata come una forma di non linearità.


This answer seems confused about some aspects of ReDos. 1. ReDoS has nothing to do with an injection attack. Injection attacks (e.g., XSS, SQL injection, command injection, etc.) are totally different. 2. ReDos is not about malicious regexps submitted by an adversary. Typically the regexp is hardcoded in the program (supplied by the developer), and the input string is supplied by a user. The problem can't be reasonably solved by input validation, because usually there's no clear input validation policy that would suffice to eliminate the problem.
D.W.

think your points amount to technicalities/ hairsplitting based on the ReDos ref & misses the forest for the trees. its similar to "crafted injection attacks". the answer points out that there are alternatives to using regexps in code. static analysis can find the "evil regexps". all the points of the answer are valid. a sentence like "typically the regexp is hardcoded in the program (supplied by the developer), and the input string is supplied by a user" doesnt exactly match the ReDos writeup which is more vague in places, and does refer to a malicious attacker etc.
vzn
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.