Superglobali che modificano direttamente


20

Ho visto persone (che generalmente scrivono un buon codice) alterare direttamente l' $_POSTarray con un codice come questo:

// Add some value that wasn't actually posted
$_POST['last_activity'] = time();

// Alter an existing post value
$_POST['name'] = trim($_POST['name']);

// Our pretend function
// Pass the entire $_POST array as data to work with in the function
// The function update_record() will read only the values we actually need
update_record($_POST);

// ...That sure was easier than creating a new array 
//  with only the $_POST values we actually need.

Ha senso che update_record()non dovrebbe accedere direttamente a $ _POST, quindi possiamo passarci altri array di dati, ad esempio, ma sicuramente questo è un design pigro, cattivo o forse solo sbagliato? Tuttavia, stiamo ancora passando un array valido a update_record(), quindi perché crearne uno nuovo?

Questo non è il punto della domanda, solo un esempio di utilizzo. Tuttavia, ho sentito molte persone dire che ciò non dovrebbe essere fatto con i $_REQUESTdati, ed è una cattiva pratica. Ma perché? Sembra abbastanza innocuo.

Esempi:

  • Impostazione di un valore predefinito $_GET(o post) che in realtà non esiste

  • Aggiunta di $_POSTvalori che non sono stati effettivamente pubblicati dopo l'invio di un modulo

  • Disinfettare o filtrare direttamente i $_GETvalori dell'array o le chiavi molto presto nello script (risanamento di fallback ... perché no?)

  • Impostazione $_POSTmanuale di un valore prima dell'invio del modulo per popolare un input con un valore predefinito (quando l'input legge $_POSTil valore predefinito; l'ho fatto)

  • Ti stai inventando i tuoi $_SERVERvalori? Certo, ehi perché no?

  • E gli altri, come $_COOKIEe $_SESSION? Certo, dobbiamo modificarli direttamente, giusto? Allora perché non gli altri?

La modifica diretta dei superglobali non dovrebbe mai essere eseguita o è corretto farlo in alcuni casi?


Concordo con # 1, # 2 e # 3 perché è un utilizzo imprevisto (in particolare # 1 e # 2).
Kevin Peno,

Buona domanda. La modifica di array globali è errata nello stesso modo in cui l'utilizzo dei valori globali è errato. Anche questi array hanno il loro scopo (passare parametri dall'esterno) che li rende un modo semplice per rovinare il codice. Ma credo che alcuni di questi array possano essere disinfettati all'inizio dello script, solo per non causare problemi all'interno del codice.
Tadeck,

1
Sto usando i wrapper di array di input OO (filtro implicito), che stampano un avviso aggiuntivo quando le variabili $ _GET o $ _POST vengono manomesse. È ancora possibile, ma dovrebbe essere limitato a situazioni ristrette. (Segnalazione cross-module, anche se solo il dispatcher / front controller dovrebbe averne bisogno.)
mario

@mario: mi piacerebbe saperne di più su come hai realizzato che se puoi dare un'occhiata a questa domanda: stackoverflow.com/questions/12954656
Wesley Murch,

Risposte:


16

Dato che PHP sta già impostando quei superglobali, non credo sia male modificarli. In alcuni casi, potrebbe essere il modo migliore per risolvere i problemi ... in particolare quando si tratta di codice di terze parti che non è possibile modificare facilmente. (Potrebbero usare $_GETdirettamente o presumere che esista una chiave in $_SERVER, ecc.)

Tuttavia, in generale, penso che sia una cattiva pratica quando si scrive il proprio codice. Modificando i $_REQUESTdati con alcuni filtri dietro le quinte che vengono eseguiti automaticamente su ogni pagina, è probabile che vengano introdotti effetti collaterali. (Vedi tutti i problemi che "citazioni magiche" hanno causato per la prova.)

Quindi, se non hai intenzione di farlo (filtra automaticamente i superglobali), allora i seguenti non ti danno alcun vantaggio:

$_POST['foo'] = filter($_POST['foo']);

quando puoi semplicemente fare:

$foo = filter($_POST['foo']);

Penso che sia molto più chiaro per fare la distinzione a livello di sito, che $_POSTe $_GETsono sempre non filtrata, i dati non attendibili, e dovrebbero mai essere usato così com'è.

Copiando il valore filtrato su un'altra variabile, stai affermando che "Capisco cosa sto facendo ... Ho filtrato questo input ed è sicuro da usare".


Grazie per l'input, la mia connessione Internet è rimasta fuori per quasi 2 giorni, quindi non ho avuto la possibilità di rispondere a nessuno. Nell'esempio, ho modificato $ _POST e l'ho usato come una matrice di dati per passare a una funzione di aggiornamento, presumendo che ci siano molti altri tasti $ _POST che leggeremo in quella funzione. Preferirei creare un nuovo array, ma invece ho visto persone fare questo, quindi sono ancora un po 'incerto se chiamarlo o meno "codice errato", ma penso che sia almeno inclinato in quel modo. Penso che ogni volta che sentirai il bisogno di farlo, c'è sempre un modo migliore.
Wesley Murch,

1
@Wesley, il motivo principale per cui è "cattivo" è che rende molto più probabile che ti dimentichi di disinfettare alcuni dati degli utenti. Nel tuo esempio, modifichi una chiave e poi passi l'intero array. Cosa succede se alcuni di questi dati contengono input dannosi che non vengono elaborati? È molto meglio costruire a mano quel nuovo array, copiando solo le cose di cui hai bisogno $_POST, igienizzando mentre procedi. E per quanto riguarda le altre persone che fanno questo ... beh, molte persone scrivono un codice PHP pessimo, ma non è una scusa per farlo. :)
konforce

Penso che avrei dovuto sottolineare le altre applicazioni dell'abuso di superglobali oltre alla semplice sanificazione dei dati. Probabilmente avrei dovuto tralasciarlo del tutto e scrivere una domanda più chiara, alla gente piace particolarmente cogliere gli aspetti della sicurezza e spesso ignorare il resto. Per non sembrare ingrato, apprezzo molto il feedback. Aspetterò un giorno e darò questo segno di spunta, dato che hai affrontato alcuni punti positivi ma hai perso la parte votante durante i 3 minuti in cui la domanda era nuova :) Grazie ancora!
Wesley Murch,

9

In generale, suggerirei di non modificare i super-globali predefiniti in modo che sia chiaro quali siano i dati sanificati e quali siano i dati grezzi / non attendibili.

Altri potrebbero suggerire che se si puliscono i superglobali all'inizio del ciclo di richiesta, non è necessario preoccuparsene altrove.

Li abbinerei sempre quando ne hai bisogno con:

$id = (int)$_POST['id'];

o simili.

In termini di altre variabili è buona norma non scrivere alle $_GET, $_POST, $_REQUEST, $_SERVERo $_COOKIE. $_SESSIONtuttavia è diverso perché spesso si desidera scrivere dati nella sessione che vengono poi mantenuti tra le diverse richieste nella sessione.


2
Un altro motivo per cui questi tipi di globi dovrebbero andare via sostituiti con oggetti / metodi che possono essere chiamati per ottenerli quando necessario. Perché setcookieesiste, ma riceviamo i cookie tramite $_COOKIE? Inoltre, poiché $_COOKIEè impostato solo all'avvio della sessione corrente e non viene mai aggiornato, è necessario modificare / impostare i cookie in entrambe le aree in modo che le aree successive del codice abbiano informazioni aggiornate.
Kevin Peno,

Grazie James, sono offline da un po ', quindi non ho potuto rispondere. Per farla breve: sono d'accordo con te. C'è sempre una soluzione migliore rispetto a scrivere per pubblicare / ottenere / etc, ma non sono ancora sicuro che sia considerata un'idea assolutamente negativa, come in " non farlo mai ". Quindi, se mi imbatto di nuovo in questo tipo di codice, pensi che abbia il diritto di "richiamarli" su un codice sciatto, o a volte può essere usato in modo intelligente e sicuro?
Wesley Murch,

@Wesley Se fosse "non farlo mai", i superglobali sarebbero probabilmente di sola lettura - non lo sono. Definirei una cattiva pratica impostarli o sovrascriverli nel codice dell'applicazione, per tali motivi.
Michel Feldheim,

3

Dovresti evitarlo. Forse qualche volta ti sei dimenticato di disinfettare qualcosa, quindi puoi recuperare dati pericolosi. Se si copiano i dati in una nuova struttura durante la sanificazione

  • Si ottiene solo, ciò che si vuole / bisogno e non ciò che è in $_POSTtroppo
  • Probabilmente verrà visualizzato un errore se all'array appena creato mancano alcune chiavi o mancano del tutto

Ulteriori altri script possono ipotizzare che l'array non sia toccato e possa reagire in modo curioso.


2

Non mi è mai piaciuta l'idea di modificare il superglobal perché è fuorviante. È un modo rapido per fare qualcosa che probabilmente ci sarà un modo migliore per farlo.

Se modifichi il valore di $_POST, ad esempio, stai dicendo che il software ha ricevuto dati che non lo hanno fatto.

IL PROBLEMA REALE

C'è una situazione di vita reale in cui questo diventa un grosso problema:

Immagina di lavorare in una squadra. In un mondo ideale, tutti usano la stessa sintassi, ma non viviamo in un mondo ideale. A uno sviluppatore, John, piace accedere ai dati pubblicati utilizzando $_POST. Cambia qualcosa nei post:

$_POST['ranking'] = 2; // John has changed ranking from 1 to 2 for whatever reason

Quindi hai un altro sviluppatore, Chris, che preferisce utilizzare filter_inputper accedere ai dati immessi (ovvero GET, POST, SERVER, COOKIE) per proteggere il software durante l'elaborazione dei dati che l'utente può manomettere. Da parte sua, deve ottenere il valore postale di ranking. La sua parte del codice è DOPO John.

$ranking = filter_input(INPUT_POST, 'ranking', FILTER_SANITIZE_NUMBER_INT);
// $ranking = 1

Dall'esempio sopra, cambiando un superglobal, hai rotto PHP. John ha impostato il valore su $_POST['ranking']2 per qualsiasi motivo, ma ora Chris ha ricevuto un valore di 1

Quando non ho visto nessun altro modo per farlo:

Ho lavorato a un progetto che utilizzava wordpress come blog per un bilanciamento del carico AWS. Questo cambia il valore di $_SERVER['remote_address']. In questo caso, l'altro sviluppatore non aveva altra scelta che fare quanto segue:

if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $parts = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
    $_SERVER['REMOTE_ADDR'] = $parts[0];
}

Conclusione

C'è quasi sicuramente un modo migliore che cambiare i superglobali


1

Penso che la vera domanda qui sia "perché dovresti modificare il tema?". Non vedo alcun motivo valido per farlo. Se devi disinfettare un imput, potresti voler usare una variabile locale ...

A meno che il tuo codice non sia abbastanza corto (diciamo, meno di 50 righe), la modifica di questi super-globali renderebbe il tuo codice più difficile da mantenere e da capire.

A proposito, non è necessario passare $ _POST alla funzione, poiché è un array superglobal a cui è possibile accedere anche nell'ambito di una funzione locale.


3
Ma dovrebbe passarlo. Altrimenti è molto difficile da testare e non è possibile chiamare la funzione / metodo con altri valori senza alcun hack (anche più brutto)
KingCrunch

Bene, dipende da cosa fa il suo metodo. Se è progettato solo per analizzare qualsiasi cosa si trovi nell'array $ _POST, non è necessario passarlo. Certo, se serve uno scopo più generale / astratto, hai ragione.

2
@Thomas, sono d'accordo con King qui. Anche se sono globali, non dovresti usare nulla di globale all'interno di altri ambiti perché causa un accoppiamento stretto (motivo per cui la funzione non può essere riutilizzata). Dato il tuo esempio, se la funzione è di disinfettare i dati, perché disinfetta solo i $_POSTdati? Il passaggio $_POSTrende la funzione igienizza qualsiasi dato.
Kevin Peno,

0

Dopo aver inizialmente risposto a questa domanda dicendo che non ci dovrebbero essere motivi per modificare i superglobali, sto modificando questa risposta con un esempio di un momento in cui ho deciso di farlo.

Attualmente sto lavorando su una tabella di database di riscrittura URL in base alla quale la requestcolonna indirizza l'utente alla targetcolonna corrispondente .

Ad esempio, a requestpotrebbe essere blog/title-heree targetpotrebbe essere blog.php?id=1.

Dal momento che blog.phpsi aspetta $_GETvariabili, e non voglio cambiare il header("Location:"), sono rimasto a fare qualcosa del genere:

$uri    = explode('?', $uri_request)[0];
$params = explode('?', $uri_request)[1];
parse_str($params, $_GET);

Questo crea un $_GETarray contenente i parametri previsti passati dalla targetcolonna.

In definitiva, consiglierei vivamente di non modificare i superglobali a meno che non sia assolutamente necessario .

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.