Ottenere pulito con PHP

La sicurezza dei dati è importante e spesso sottovalutata da designer, sviluppatori e clienti. Dal PHP 5.2.0, la disinfezione e la convalida dei dati sono state rese significativamente più semplici con l'introduzione del filtraggio dei dati. Oggi esamineremo da vicino questi filtri, come usarli e costruiremo alcune funzioni personalizzate.

Dettagli dell'esercitazione

  • Programma: PHP
  • Versione: 5.2.0+
  • Difficoltà: Principiante
  • Tempo di completamento stimato: 20 minuti

introduzione

Ho sempre pensato che sia facile scrivere codice in PHP, e ancora più facile scrivere codice cattivo in PHP. La proliferazione di PHP sul web è stata davvero aiutata dal suo uso in popolari pacchetti software open-source come WordPress, Drupal e Magento, nonché nelle principali applicazioni web come Facebook; con PHP utilizzato in così tante diverse istanze (siti Web dinamici, applicazioni Web approfondite, piattaforme di blogging, sistemi di gestione dei contenuti ed e-commerce essendo solo un sottoinsieme delle numerose applicazioni di PHP) le opportunità per sporco i dati e i sistemi insicuri sono numerosi. Questo tutorial spiegherà alcuni metodi di Ottenere pulito con PHP: disinfezione e convalida dei dati concentrandosi su diverse forme di input di dati e su come utilizzare i filtri PHP e le funzioni personalizzate.

Perché disinfettare e convalidare?

In questo tutorial, siamo davvero concentrati sugli input di dati che gli utenti o le fonti esterne potrebbero fornire. Ciò significa che non controlliamo i dati che stiamo ricevendo. Tutto ciò che possiamo fare è controllare cosa viene fatto dopo averlo ricevuto. Esistono tutti i tipi di minacce relative alla sicurezza dei dati da input dell'utente e dati di terze parti.

Alcuni un-diffuse minacce alla sicurezza dei dati:

  • Cross-Site Scripting (XSS): Una forma di iniezione di codice in cui uno script viene iniettato su un sito Web da un sito Web completamente diverso. Questa è di gran lunga la vulnerabilità di sicurezza più comune online. Due esempi recenti di questa tecnica sono gli Stalk Daily e Mikeyy Twitter Worms di quest'anno che utilizzavano input scarsamente igienizzati per lanciare Javascript tramite un'interfaccia web Twitter "infetta".
  • SQL Injection: La seconda vulnerabilità di sicurezza più comune in linea, questa è un'altra forma di iniezione di codice in cui uno script viene utilizzato per partecipare a uno dei numerosi comportamenti di sfruttamento incluso (ma non limitato a) l'esposizione e / o l'accesso non autorizzato ai dati, la modifica dei dati all'interno di un database, o semplicemente iniettando il codice da rendere o eseguire all'interno di un sito Web rompendo o alterando il sito web.
  • Falsificazione richiesta tra siti (CSRF / XSRF): Un exploit meno comune che si basa più su fonti di dati come browser e cookie di sessione che input di dati scarsamente igienizzati e convalidati, CSRF (pronunciato "sea-surf") può essere utilizzato per eseguire comandi su un sito Web senza il permesso dell'utente. Un metodo CSRF popolare utilizza un URI di dati immagine formato in modo improprio o un valore src per eseguire uno script anziché visualizzare un'immagine.
  • Dati impropri: Non proprio una "vulnerabilità di sicurezza" di per sé, dati impropri possono causare host di problemi per il proprietario di un sito web o l'amministratore del database. Spesso, i dati impropri possono danneggiare siti Web mal codificati o causare l'arresto anomalo dei sistemi automatizzati. Un esempio di questo è stata la possibilità di alterare intere pagine del profilo MySpace pubblicando utilizzando tutti i tipi di hackery HTML / CSS (Nota: questo potrebbe ancora funzionare, non ho usato MySpace da molto tempo).
Fonte immagine: XKCD

Per i nostri scopi, ci concentreremo solo sui metodi lato server per migliorare la sicurezza dei dati con PHP, quindi vediamo come i termini "sanitizzazione" e "validazione" sono definiti in relazione a PHP. Secondo il manuale PHP:

La convalida viene utilizzata per convalidare o verificare se i dati soddisfano determinati requisiti. Ad esempio, il passaggio in FILTER_VALIDATE_EMAIL determinerà se i dati sono un indirizzo email valido, ma non cambieranno i dati stessi.

La sanitizzazione disinfetterà i dati, quindi potrebbe modificarli rimuovendo caratteri indesiderati. Ad esempio, il passaggio in FILTER_SANITIZE_EMAIL rimuoverà i caratteri che sono inappropriati per un indirizzo email da contenere. Detto questo, non convalida i dati.

In sostanza, se il tuo sito web è la discoteca in cui tutti vogliono entrare, la convalida verifica la lista degli ospiti e gli ID sulla porta mentre l'igienizzazione funge da buttafuori che elimina gli indesiderabili che capita di cigolare. Con questo in mente, diamo un'occhiata a PHP Filters Extension.

Che filtri ho??

Tutte le installazioni PHP non sono uguali. Mentre PHP 5.2.0 era l'introduzione dei filtri, non tutte le installazioni hanno lo stesso set di filtri nella loro estensione di filtri. La maggior parte delle installazioni avrà tutti i filtri che andremo a vedere, ma per insegnarti un po 'sull'estensione dei filtri, scopriremo solo ciò che hai sul tuo server. Nel download sorgente, ho incluso un file chiamato getfilters.php questo, una volta installato ed eseguito sul tuo server, mostrerà tutti i tuoi filtri (entrambi i filtri di dati disponibili attraverso il filter_var filtri di funzioni e stream disponibili attraverso stream_filter_append).

 eco "

Filtri dati

\ n\ n\ n "; echo"\ n "; echo"\ n"; foreach (filter_list () come $ id => $ filter) echo"\ n "; echo"
Filtro IDNome del filtro
Filtro $".Filter_id ($ filtro)."
\ N ";

Innanzitutto, otteniamo la matrice contenente l'elenco di tutti i filtri disponibili con filter_list, quindi eseguiamo un ciclo attraverso la matrice e riecheggiamo il nome del filtro, scopriamo l'ID assegnato dal filtro ed echo anche questo ID.

Come faccio ad usare un filtro?

I filtri PHP per la convalida e la disinfezione vengono attivati ​​passando almeno due valori alla funzione Estensione filtri PHP filter_var. Ad esempio, utilizziamo il filtro Sanitize per un numero intero in questo modo:

 $ value = '123abc456def'; echo filter_var ($ value, FILTER_SANITIZE_NUMBER_INT);

Nell'esempio, abbiamo una variabile $ value che è passato attraverso la funzione di estensione dei filtri filter_var usando il FILTER_SANITIZE_NUMBER_INT filtro. Ciò risulta nell'output seguente:

 123456

Il filtro Sanitize per un numero intero rimuove tutti i caratteri non interi dall'output e produce un intero pulito. All'interno del codice sorgente del download, puoi provare vari input e applicherà una serie di filtri comuni al tuo valore di input. Ho incluso un certo numero di stringhe di esempio differenti che puoi testare anche tu.

Cosa fanno i diversi filtri??

L'elenco seguente non è completo, ma contiene la maggior parte dei filtri forniti di serie con le installazioni 5.2.0+. I filtri personalizzati e quelli aggiunti dalle estensioni personalizzate non sono inclusi qui.

FILTER_VALIDATE_BOOLEAN: Controlla se i dati passati al filtro sono o meno un valore booleano di VERO o FALSE. Se il valore è un valore non booleano, verrà restituito FALSE. Lo script seguente echo "TRUE" per i dati di esempio $ value01 ma echo "FALSE" per i dati di esempio $ value02:

 $ value01 = TRUE; if (filter_var ($ value01, FILTER_VALIDATE_BOOLEAN)) echo 'TRUE';  else echo 'FALSE';  eco '

'$ value02 = TRUE; if (filter_var ($ value02, FILTER_VALIDATE_BOOLEAN)) echo 'TRUE'; else echo 'FALSE';

FILTER_VALIDATE_EMAIL: Controlla se i dati passati al filtro sono o meno un indirizzo e-mail potenzialmente valido. Non controlla se l'indirizzo e-mail esiste realmente, solo che il formato dell'indirizzo e-mail è valido. Lo script seguente echo "TRUE" per i dati di esempio $ value01 ma echo "FALSE" per i dati di esempio $ value02 (perché il secondo manca della porzione @ domain.tld necessaria dell'indirizzo e-mail):

 $ value01 = '[email protected]'; if (filter_var ($ value01, FILTER_VALIDATE_EMAIL)) echo 'TRUE';  else echo 'FALSE';  eco '

'$ value02 =' nettuts '; if (filter_var ($ value02, FILTER_VALIDATE_EMAIL)) echo 'TRUE'; else echo 'FALSE';

FILTER_VALIDATE_FLOAT: Verifica se i dati passati al filtro sono o meno validi. Lo script seguente echo "TRUE" per i dati di esempio $ value01 ma echo "FALSE" per i dati di esempio $ value02 (perché i separatori di virgola non sono consentiti nei valori float):

 $ value01 = '1.234'; if (filter_var ($ value01, FILTER_VALIDATE_FLOAT)) echo 'TRUE';  else echo 'FALSE';  eco '

'$ value02 =' 1.234 '; if (filter_var ($ value02, FILTER_VALIDATE_FLOAT)) echo 'TRUE'; else echo 'FALSE';

FILTER_VALIDATE_INT: Controlla se i dati passati al filtro sono o meno un valore intero valido. Lo script seguente echo "TRUE" per i dati di esempio $ value01 ma echo "FALSE" per i dati di esempio $ value02 (perché le frazioni / i numeri decimali non sono numeri interi):

 $ value01 = '123456'; if (filter_var ($ value01, FILTER_VALIDATE_INT)) echo 'TRUE';  else echo 'FALSE';  eco '

'$ value02 =' 123.456 '; if (filter_var ($ value02, FILTER_VALIDATE_INT)) echo 'TRUE'; else echo 'FALSE';

FILTER_VALIDATE_IP: Verifica se i dati passati al filtro sono o meno un indirizzo IP potenzialmente valido. Non controlla se l'indirizzo IP si risolve, solo che si adatta alla struttura dei dati richiesta per gli indirizzi IP. Lo script seguente echo "TRUE" per i dati di esempio $ value01 ma echo "FALSE" per i dati di esempio $ value02:

 $ value01 = '192.168.0.1'; if (filter_var ($ value01, FILTER_VALIDATE_IP)) echo 'TRUE';  else echo 'FALSE';  eco '

'$ value02 =' 1.2.3.4.5.6.7.8.9 '; if (filter_var ($ value02, FILTER_VALIDATE_IP)) echo 'TRUE'; else echo 'FALSE';

FILTER_VALIDATE_URL: Verifica se i dati trasmessi al filtro sono o meno un URL potenzialmente valido. Non controlla se l'URL si risolve, ma solo che si adatta alla struttura dei dati richiesta per gli URL. Lo script seguente echo "TRUE" per i dati di esempio $ value01 ma echo "FALSE" per i dati di esempio $ value02:

 $ value01 = 'http://net.tutsplus.com'; if (filter_var ($ value01, FILTER_VALIDATE_URL)) echo 'TRUE';  else echo 'FALSE';  eco '

'$ value02 =' nettuts '; if (filter_var ($ value02, FILTER_VALIDATE_URL)) echo 'TRUE'; else echo 'FALSE';

FILTER_SANITIZE_STRING: Per impostazione predefinita, questo filtro rimuove tutti i dati da una stringa non valida o non consentita in quella stringa. Ad esempio, questo rimuoverà qualsiasi tag HTML, come '; echo filter_var ($ value, FILTER_SANITIZE_STRING);

Questo script rimuove i tag e restituisce quanto segue:

 avviso ('TROUBLE HERE');

FILTER_SANITIZE_ENCODED: Molti programmatori usano PHP UrlEncode () funzione per gestire la loro codifica URL. Questo filtro essenzialmente fa la stessa cosa. Ad esempio, codificherà qualsiasi spazio e / o carattere speciale da una stringa di input:

 $ value = ''; echo filter_var ($ value, FILTER_SANITIZE_ENCODED);

Questo script codifica la punteggiatura, gli spazi e le parentesi, quindi restituisce quanto segue:

 % 3Cscript% 3Ealert% 28% 27TROUBLE% 20HERE% 27% 29% 3B% 3C% 2Fscript% 3E

FILTER_SANITIZE_SPECIAL_CHARS: Questo filtro, per impostazione predefinita, codifica in HTML caratteri speciali come virgolette, e commerciali e parentesi (oltre ai caratteri con valore ASCII inferiore a 32). Mentre la pagina dimostrativa non lo rende abbondantemente chiaro senza visualizzare la fonte (perché i caratteri speciali codificati in HTML saranno interpretati e renderizzati), se dai un'occhiata al codice sorgente vedrai la codifica al lavoro:

 $ value = ''; echo filter_var ($ value, FILTER_SANITIZE_SPECIAL_CHARS);

Converte i caratteri speciali nei loro sé codificati in HTML:

 

FILTER_SANITIZE_EMAIL: Questo filtro fa esattamente ciò che si penserebbe che faccia. Rimuove tutti i caratteri che non sono validi negli indirizzi e-mail (come parentesi, parentesi, due punti, ecc.). Ad esempio, supponiamo che tu abbia accidentalmente aggiunto le parentesi su una lettera del tuo indirizzo e-mail (non chiedere come, usa la tua immaginazione):

 $ value = 't (e) [email protected]'; echo filter_var ($ value, FILTER_SANITIZE_EMAIL);

Rimuove quelle parentesi e ottieni il tuo bellissimo indirizzo e-mail:

 [email protected]

Si tratta di un ottimo filtro da utilizzare sui moduli di posta elettronica di concerto con FILTER_VALIDATE_EMAIL per ridurre gli errori degli utenti o impedire gli attacchi relativi a XSS (poiché alcuni attacchi XSS precedenti riguardavano il ritorno dei dati originali forniti in un campo di posta elettronica non disinfettato direttamente al browser).

FILTER_SANITIZE_URL: Simile al filtro di disinfezione degli indirizzi e-mail, questo filtro fa esattamente quello che si potrebbe pensare. Rimuove tutti i caratteri che non sono validi in un URL (come certi caratteri UTF-8, ecc.). Ad esempio, diciamo che hai accidentalmente aggiunto un "®" nell'URL del tuo sito web (di nuovo, non chiedere come, fingere che un velociraptor l'abbia fatto):

 $ value = 'http: //net.tuts®plus.com'; echo filter_var ($ value, FILTER_SANITIZE_URL);

Rimuove l'indesiderato "®" e ottieni il tuo bellissimo URL indietro:

 http://net.tutsplus.com

FILTER_SANITIZE_NUMBER_INT: Questo filtro è simile a FILTER_VALIDATE_INT ma, invece di controllare semplicemente se è un numero intero o meno, in realtà rimuove tutto il valore non intero dal valore! Pratico, infatti, per fastidiosi spambots e tricksters in alcune forme di input:

 $ value01 = '123abc456def'; echo filter_var ($ value01, FILTER_SANITIZE_NUMBER_INT); eco '
'; $ value02 = '1.2.3.4.5.6.7.8.9'; echo filter_var ($ value02, FILTER_SANITIZE_NUMBER_INT);

Quelle sciocche lettere e cifre decimali vengono buttate fuori:

 123456 123456789

FILTER_SANITIZE_NUMBER_FLOAT: Questo filtro è simile a FILTER_VALIDATE_INT ma, invece di controllare semplicemente se è un numero intero o meno, in realtà rimuove tutto il valore non intero dal valore! Pratico, infatti, per fastidiosi spambots e tricksters in alcune forme di input:

 $ value01 = '123abc456def'; echo filter_var ($ value01, FILTER_SANITIZE_NUMBER_FLOAT); eco '
'; $ value02 = '1.2.3.4.5.6.7.8.9'; echo filter_var ($ value02, FILTER_SANITIZE_NUMBER_FLOAT);

Ancora una volta, tutte quelle stupide lettere e decimali vengono buttate fuori:

 123456 123456789

Ma cosa succede se si desidera mantenere un decimale come nel prossimo esempio:

 $ value = '1,23'; echo filter_var ($ value, FILTER_SANITIZE_NUMBER_FLOAT);

Rimuoverà comunque e restituirà:

 123

Uno dei motivi principali per cui FILTER_SANITIZE_NUMBER_FLOAT e FILTER_SANITIZE_INT sono filtri separati è quello di consentire ciò tramite uno speciale flag "FILTER_FLAG_ALLOW_FRACTION" che viene aggiunto come terzo valore passato a filter_var:

 $ value = '1,23'; echo filter_var ($ value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);

Manterrebbe il decimale e restituirà:

 1.23

Opzioni, flag e controlli di array, OH MY!

Il flag in questo ultimo esempio è solo una delle molte più opzioni, flag e controlli di array che consentono di avere un controllo più granulare su quali tipi di dati vengono disinfettati, definizioni di delimitatori, come gli array vengono elaborati dai filtri e altro. Puoi trovare ulteriori informazioni su questi flag e su altre funzioni relative ai filtri nella sezione Estensione dei filtri del manuale PHP.

Altri metodi di Santizing Data con PHP

Ora, esamineremo alcuni metodi supplementari di sanificazione dei dati con PHP per evitare che "dati sporchi" causino il caos sui vostri sistemi. Questi sono particolarmente utili per le applicazioni che eseguono ancora PHP 4, poiché erano tutte disponibili al momento del rilascio.

htmlspecialchars: Questa funzione PHP converte 5 caratteri speciali nelle rispettive entità HTML corrispondenti:

  • '&' (e commerciale) diventa '&'
  • '"' (virgoletta doppia) diventa '"' quando ENT_NOQUOTES non è impostato.
  • "(virgoletta singola) diventa" "solo quando ENT_QUOTES è impostato.
  • '<' (less than) becomes '<'
  • '>' (maggiore di) diventa '>'

È usato come qualsiasi altra funzione di stringa PHP:

 echo htmlspecialchars ('$ stringa');

htmlentities: Come htmlspecialchars, questa funzione PHP converte i caratteri nelle rispettive entità HTML. La grande differenza è questa TUTTI i caratteri che possono essere convertiti saranno convertiti. Questo è un metodo utile per offuscare gli indirizzi e-mail di alcuni robot che raccolgono indirizzi e-mail, poiché non sono programmati per leggere htmlentities.

È usato come qualsiasi altra funzione di stringa PHP:

 echo htmlentities ('$ stringa');

mysql_real_escape_string: Questa funzione MySQL aiuta a proteggere dagli attacchi SQL injection. È considerata una best practice (o anche una pratica obbligatoria) per passare tutti i dati che vengono inviati a una query MySQL attraverso questa funzione. Sfugge a qualsiasi personaggio speciale che potrebbe essere problematico e potrebbe causare a Bobby Tables un altro database di studenti scolastici.

 $ query = 'SELECT * FROM table WHERE value = ". mysql_real_escape_string (" $ string'). " LIMITE 1,1 '; $ runQuery = mysql_query ($ query);

Funzioni personalizzate

Per molte persone, questi filtri e funzioni integrati non sono abbastanza buoni. La convalida dei dati di alcuni dati come numeri di telefono, codici postali o anche e-mail richiede spesso una convalida e un mascheramento più severi. Per fare ciò, molte persone creano funzioni personalizzate per la convalida e i loro dati sono reali. Un esempio di questo può essere semplice come utilizzare una query MySQL per cercare i dati in un database di valori noti come:

 function checkZipCode ($ value) $ zipcheck = 'SELECT COUNT (*) FROM' database '.' zipcodes 'WHERE value = "'. filter_var (mysql_real_escape_string ($ value), FILTER_SANITIZE_NUMBER_INT). '"' '; $ count = mysql_query ($ zipcheck); if ($ count == 1) return TRUE;  else return FALSE; 

È possibile creare altre funzioni personalizzate che non si basano su database di valori noti e possono essere create controllando le virgolette magiche, le barre di separazione e l'escaping per l'inserimento in un database:

 function cleanString ($ string) $ detagged = strip_tags ($ string); if (get_magic_quotes_gpc ()) $ stripped = stripslashes ($ detagged); $ escaped = mysql_real_escape_string ($ stripped);  else $ escaped = mysql_real_escape_string ($ detagged);  return $ escaped; 

Le possibilità sono infinite, specialmente se si integrano le espressioni regolari, ma per la maggior parte delle volte, l'estensione dei filtri PHP dovrebbe fare il trucco.

  • Seguici su Twitter o iscriviti al feed Nettuts + RSS per altri articoli e tutorial di sviluppo web quotidiano.