2010-03-03 3 views
5

Desidero creare un sito Web in cui gli utenti possano testare le espressioni regolari (ce ne sono molte già là fuori ... come questo: http://www.pagecolumn.com/tool/pregtest.htm). Fondamentalmente, l'utente fornisce un'espressione regolare e del testo di esempio, ei risultati della valutazione regex saranno restituiti.Sanitizzazione delle espressioni regolari fornite dall'utente in PHP

Voglio valutare la regex sul lato server con le funzioni PHP "preg_ *". C'è un modo per disinfettare la regex fornita? Quali sono le vulnerabilità di sicurezza di cui dovrei preoccuparmi?

+0

Perché non usi JS per quello? In questo modo non devi disinfettare nulla poiché verrà eseguito sul lato client. – Daan

+0

Avrei dovuto aggiungere che oltre a valutare la regex sul testo di esempio fornito dall'utente, voglio anche valutare la regex su una stringa "segreta", che risiede sul server. Non conosco un modo per farlo in JS senza che l'utente sappia cosa sia la stringa. –

risposta

3

Penso che PHP stesso verificherà la regex. Ecco uno script di esempio che ho fatto:

// check for input, and set max size of input 
if(@!empty($_POST['regex']) 
    && @!empty($_POST['text']) 
    && strlen($_POST['regex'])<1000 
    && strlen($_POST['text'])<2000 
    ){ 
    // set script timeout in case something goes wrong (SAFE MODE must be OFF) 
    $old_time=ini_get('max_execution_time'); 
    if(!set_time_limit(1)) die('SAFE MODE MUST BE OFF'); // 1 sec is more then enough 

    // trim input, it's up to you to do more checks 
    $regex=trim($_POST['regex']); 
    // don't trim the text, it can be needed 
    $input=$_POST['text']; 
    // escape slashes 
    $regex=preg_replace('/([\\/]+)?//', '\/', $regex); 

    // go for the regex 
    if([email protected]_match('/'.$regex.'/', $input, $matches)){ 
      // regex was tested, show results 
      echo 'Matches: '.$matched.'<br />'; 
      if($matched>0){ 
        echo 'matches: <br />'; 
        foreach($matches as $i => $match){ 
          echo $i.' = '.$match.'<br />'; 
       } 
      } 
    } 
    // set back original execution time 
    set_time_limit($old_time); 
} 

In ogni modo, MAI MAI usare eval() con l'utente stringhe presentate.

Inoltre, è possibile eseguire una semplice sanificazione minimalista, ma dipende da voi. ;)

+1

invece di eseguire l'escape della stringa regex da solo, è possibile utilizzare [preg_quote] (http://php.net/preg_quote) – MarcDefiant

+0

Sei sicuro che l'impostazione di max_execution_time limiterà effettivamente il tempo in cui è in esecuzione?Avevo l'impressione che le chiamate DL sarebbero sempre state completate e che max_execution_time avrebbe solo fatto scadere lo script php dopo la chiamata di preg. Ciò significherebbe che gli utenti potrebbero ancora facilmente impantanare il tuo sistema fornendo espressioni malvagie. – brightbyte

0

L'unico problema a cui riesco a pensare è che qualcuno può eseguire il DOS inserendo una espressione regolare negativa (una che è O (2^n) o O (n!) O qualsiasi altra cosa) e il modo più semplice per evitare che ciò possa essere per impostare il timeout della pagina breve.

+0

... o limitare il livello di backtrace di PREG. – Xeoncross

0

Se l'espressione regolare viene archiviata in un database, è necessario utilizzare qualsiasi metodo si utilizzi normalmente per evitare i dati, ad esempio istruzioni preparate.

Altrimenti, la mia unica preoccupazione è che l'utente possa fornire regex dannose nel senso che potrebbe contenere una regex complessa malriposta, e non sono sicuro che ci sia un modo per verificarlo.

Un pensiero è che si potrebbe rendere il tuo valutatore di espressioni regolari tutto il lato client eseguendolo in JS, ma ci sono incoerenze tra le funzioni di preg di php e le funzioni di regex di JavaScript.

0

Afaik ora ci sono "vulnerabilità" quando si tenta di valutare espressioni regolari fornite dall'utente. La cosa peggiore che potrebbe accadere è - come dice erik - un attacco DOS o un errore fatale all'interno del tuo script.

Ho paura di dirti che non sarai (nemmeno in teoria) in grado di "disinfettare" ogni possibile espressione regolare. Il meglio che puoi fare è verificare errori lessicali e/o sintattici.

1

Se si autorizzano i valori inviati dall'utente per preg_replace, assicurarsi che non consenta lo e flag! Non farlo potrebbe consentire a un utente malintenzionato di eliminare l'intero sito o, peggio.

Altrimenti, la cosa peggiore che può succedere è quello che le altre risposte già indicano. Imposta un timeout di script basso, e forse dovresti anche assicurarti che la pagina possa essere chiamata solo X volte al minuto.