2010-08-17 9 views

risposta

7

Lascia perdere. La whitelist della funzione affidabile non è possibile in php. Esempio:

$x = 'e' . str_replace('y', 'x', 'yec'); 
...lots of code... 
$x('format c:'); 

realistici opzioni sono

+1

@stereofrog Ecco perché non sto consigliarlo. Sentiti libero di modificare la mia risposta per renderla meno confusa. Sono terribile alle spiegazioni. – NullUserException

+0

Non dovrebbe essere "Funzione affidabile ** whitelisting ** è impossibile in PHP"? Perché la lista nera è possibile usando disable_functions. – wimvds

+0

Non l'ho notato, lo modifico quindi: p. – wimvds

1

Dare agli utenti la possibilità di inserire il codice PHP è veramente pericoloso . Prendi in considerazione tutte le altre opzioni prima di implementare questo. Una specie di costruttore di codice PHP. Ispirato a un costruttore di query.

Se si decide di consentire il codice PHP da parte dei client, è preferibile utilizzare una whitelist. È necessario utilizzare espressioni regolari per estrarre queste funzioni dal codice pubblicato.

+4

PHP non è una lingua normale. – Gumbo

+0

@ Gumbo: per favore, spieghi che cosa ha a che fare con questa situazione? –

+1

@Stegeman Non è possibile utilizzare espressioni regolari su una lingua non regolare. – NullUserException

1

Quello che ci si aspetta che faccia è un lavoro estremamente duro se si vuole farlo bene. Vorrei iniziare parsing il codice PHP inserito, controllando ogni chiamata di funzione, non consentendo backticks del tutto, ecc

In altre parole: se si desidera consentire a un sottoinsieme di PHP è necessario implementare il proprio lexer (anche se PHP fornisce un parser fuori dalla scatola).

2

Per quanto ne so, è possibile utilizzare solo un approccio black-list:

Naturalmente, è necessario considerare come fattibile è quello di mantenere la un elenco aggiornato di tutte le funzioni integrate definite da tutte le possibili estensioni.

Un'altra possibilità mi viene in mente sta scrivendo un semplice tokenizzatore:

http://es2.php.net/manual/en/function.token-get-all.php

È quindi possibile controllare le funzioni utilizzate contro una lista bianca.

Aggiornamento: Ho avuto l'impressione sbagliata che token_get_all() sarebbe identificare le chiamate di funzione, ma in realtà non lo fa. Sono tutti T_STRING s.

+0

+1, non capisco perché la gente tende a complicare eccessivamente problemi come questi, sovrastimolandola non renderla più sicura, attenersi ai metodi originali come 'disable-functions' e' disable-classes' – RobertPitt

+0

@stereofrog, ho capito cosa intendevi (non dici veramente) e ho modificato il mio post di conseguenza. –

+0

La documentazione relativa ai token di PHP.net è piuttosto carente. Lasciano fuori determinati token e definiscono erroneamente alcuni token - o quello o il loro uso da 'token_get_all()' e dai messaggi di avviso/errore di PHP sono diversi, e stanno andando da quest'ultimo. –

2

L'opzione più sicura e facile da mantenere sarà la programmazione di un "mini-linguaggio" dedicato in php. Puoi renderlo un sottoinsieme di php o renderlo simile alle formule di Excel o persino inventare il tuo. In questo modo avrai sempre il pieno controllo di ciò che sta accadendo.

//

solo per divertimento, ecco una piccola Lisp per voi

function lisp($x) { 

    if(is_string($x)) { 
     $re = '~\(([^()]*)\)~'; 
     while(preg_match($re, $x)) 
      $x = preg_replace_callback($re, 'lisp', $x); 
     return trim($x); 
    } 

    $x = preg_split('~\s+~', $x[1]); 
    $e = array_shift($x); 
    if(!$x) 
     return is_numeric($e) ? floatval($e) : $e; 

    switch($e) { 
     case '+': return lisp($x[0]) + lisp($x[1]); 
     case '-': return lisp($x[0]) - lisp($x[1]); 
     case '*': return lisp($x[0]) * lisp($x[1]); 
     case '/': return lisp($x[0])/lisp($x[1]); 

     case 'concat': return lisp($x[0]) . lisp($x[1]); 
    } 

    return function_exists($e) ? 
     call_user_func_array($e, array_map('lisp', $x)) : ''; 
} 

$input = ' 
    (strtolower 
     (concat 
      (strrev olleh) 
      (+ 22 20)))'; 

echo lisp($input); // hello42 

;))

+0

Questo è potenzialmente un * lotto * di lavoro. – NullUserException

+0

È possibile creare un lisp-1 con ambito dinamico. Non devi dirgli che è una liscivia. Oppure, se preferisci, puoi ottenere LIME per PHP e implementare l'algebra infissa, magari all'interno di [parentesi quadre] e creare qualcosa che assomigli a TCL. Perché deve assomigliare al PHP? – Ian

+0

oppure Puoi scrivere un parser di un sottoinsieme di PHP in PHP ed eseguire solo le funzioni selezionate! : D – naugtur

Problemi correlati