Rischio per la sicurezza? $ _POST variabili ... $$ sullo stack locale
Domanda
I stava parlando con uno dei miei programmatori in precedenza e mi ha mostrato un pezzo di codice che stava pensando:
foreach($_REQUEST as $var=>$val) {
$$var = addslashes($val);
}
Voleva essere in grado di utilizzare $varName
invece di dover scrivere $_REQUEST['varName']
Gli ho consigliato di utilizzare il mysql_real_escape_string
invece di addSlashes
e di non mettere le variabili $_REQUEST
nello stack locale, perché questo dà un hacker allegare vettoriale. A me sembra che lo stesso problema che la vecchia direttiva REGISTER_GLOBALS
aveva.
Ha detto che non c'era la stessa rischi per la sicurezza, perché le variabili sono stati tutti creati sullo stack locale. Quindi ero incerto e ho controllato la pagina variabili variabile PHP all'indirizzo: http: //www.php.net/manual/en/language.variables.variable.php ma ha visto alcun riferimento a Super Globals e sicurezza altri poi la finestra di avvertimento.
Gli hacker possono facilmente approfittare di questo costrutto?
Soluzione
Questo è come tornare indietro di 6 anni di miglioramenti alla sicurezza PHP ... Fondamentalmente, register_globals
e magic_quotes
messi insieme! Quei due sono contrassegnati deprecato nelle ultime versioni di PHP, e saranno rimossi da future versioni, per ottime ragioni.
Immaginate il seguente codice:
if ($is_admin) {
do_administrative_task();
}
Ora qualcuno fa la seguente richiesta:
http://www.example.com/script.php?is_admin=1
E proprio così, sei amministratore!
Allo stesso modo, addslashes()
in realtà non fornisce alcuna protezione contro gli attacchi di SQL injection, perché non capisce i set di caratteri moderni. E 'ridicolmente facile mestiere qualcosa che bypass addslashes()
e PWN il database.
Altri suggerimenti
Non ho codificato php in anni, ma non c'è una funzione che fa questo? Forse chiamato estratto ?
Ci sono un paio di avvertimenti circa utilizzando tale funzione con i dati utente immessi .. questi avvertimenti si applicherebbe a snippet di codice pure.
Il "stack locale" non ha nulla a che fare con esso. Esso consente ancora a chiunque di creare una nuova variabile in qualche parte del codice che il programmatore non può aver anctipated.
Se davvero vuole prendere i parametri di richiesta di $_REQUEST
e fare le variabili di tutti, allora dovrebbe trasferire solo quelli che il codice sta per cercare e non di più.
E addslashes()
fosso. Che non è solo il luogo sbagliato per sfuggire dati in arrivo, ma la funzione sbagliata, troppo.
Sì. Se l'URL della richiesta contiene ...&GLOBALS[var]=1
allora sovrascriverà la variabile globale secondo.
Si dovrebbe almeno prendere in considerazione seguente costrutto per la sicurezza:
extract($_REQUEST, EXTR_PREFIX_ALL, "var_"); // or EXTR_SKIP
Questo vi darà le variabili localizzate almeno un prefisso e impedire la sovrascrittura delle variabili globali. Per buona misura anche l'uso array_map("addslashes", $_REQUEST)
o una funzione di fuga più appropriato. Ma in realtà, questo è solo magic_quotes con un altro nome. (Offtopic:. Cercare di lasciar andare via mysql_query e utilizzare DOP e prepared statement, che è più semplice e più sicuro)
Proprio così! Come il programmatore in questione ci sono in realtà tre questioni separate qui.
- Questo
$_REQUEST
non è più insicuro di$_GET
o$_POST
visto che da PHP impostazione predefinita$_COOKIES
ha la precedenza su$_GET
e$_POST
. - Impostazione valore di un superglobale è più sicuro di una variabile locale in una funzione o una variabile locale metodo di un oggetto.
- utente finale variabile creata in funzione sono globalmente accessibile.
La partenza di Let in alto.
-
$_POST
e$_GET
non sono più sicuro di$_REQUEST
. Tutte le informazioni ricevute da un form è sporca. Periodo. Indipendentemente. Se posso inviare nei cookie falsi ho il know how per le variabiliPOST
falsi. L'argomento è discutibile. - Quindi prendiamo una variabile locale che creiamo con
$var.
La portata di questa variabile è soltanto all'interno della funzione / metodo. È l'impostazione del contenuto di una superglobale al valore dei dati forniti dall'utente più sicura di una variabile locale che viene allo scrub quando lo stack funzione / metodo viene pulita? Mi chiedo ... - Consente di prendere un frammento
function some_function() {
foreach($_POST as $var=>$val) {
$$var = $val;
}
}
Ora, se $_POST
contiene una variabile denominata _POST
questo codice imposterà un $_POST
variabile locale contenente il valore. Tuttavia, superglobals ignorerà questa e qualsiasi riferimento $_POST
riconosceranno l'superglobale, non la variabile locale e come tale la $_POST
locale è unrefereceable. Data questa funzionalità di PHP, senza utilizzare la parola chiave globale che di norma è impossibile ignorare completamente il superglobale