Fermare!
Stai commettendo un errore qui. Oh, no, hai scelto le giuste funzioni PHP per rendere i tuoi dati un po 'più sicuri. Va bene. Il tuo errore è nell'ordine delle operazioni e come e dove utilizzare queste funzioni.
È importante comprendere la differenza tra la sanificazione e la convalida dei dati utente, la fuga dei dati per l'archiviazione e la fuga dei dati per la presentazione.
Disinfezione e convalida dei dati utente
Quando gli utenti inviano dati, devi assicurarti che abbiano fornito qualcosa che ti aspetti.
Sanificazione e filtraggio
Ad esempio, se si prevede un numero, assicurarsi che i dati inviati siano un numero . Puoi anche trasmettere i dati utente in altri tipi. Tutto ciò che viene inviato viene inizialmente trattato come una stringa, quindi forzare i dati numerici noti a diventare numeri interi o float rende la sanificazione rapida e indolore.
Che dire di campi di testo in formato libero e textareas? Devi assicurarti che non ci sia nulla di inaspettato in quei campi. Principalmente, è necessario assicurarsi che i campi che non dovrebbero avere alcun contenuto HTML non contengano effettivamente HTML. Esistono due modi per affrontare questo problema.
Innanzitutto, puoi provare a sfuggire all'input HTML con htmlspecialchars
. Non dovresti usare htmlentities
per neutralizzare l'HTML, poiché eseguirà anche la codifica di caratteri accentati e di altri caratteri che ritiene debbano essere codificati.
In secondo luogo, puoi provare a rimuovere qualsiasi HTML possibile. strip_tags
è semplice e veloce, ma anche sciatto. HTML Purifier fa un lavoro molto più completo sia eliminando tutto l'HTML sia consentendo una whitelist selettiva di tag e attributi.
Le moderne versioni di PHP vengono fornite con l'estensione del filtro , che fornisce un modo completo per disinfettare l'input dell'utente.
Validazione
Assicurarsi che i dati inviati siano privi di contenuti imprevisti è solo metà del lavoro. Devi anche provare e assicurarti che i dati inviati contengano valori su cui puoi effettivamente lavorare.
Se ti aspetti un numero compreso tra 1 e 10, devi verificare quel valore. Se stai utilizzando uno di quei nuovi fantasiosi input numerici dell'era HTML5 con uno spinner e passaggi, assicurati che i dati inviati siano in linea con il passaggio.
Se i dati provengono da quello che dovrebbe essere un menu a discesa, assicurarsi che il valore inviato sia quello visualizzato nel menu.
Che dire degli input di testo che soddisfano altre esigenze? Ad esempio, gli input di data devono essere convalidati tramite strtotime
la classe DateTime . La data indicata deve essere compresa tra gli intervalli previsti. E gli indirizzi e-mail? L' estensione di filtro menzionata in precedenza può verificare che un indirizzo sia ben formato, anche se sono un fan della libreria is_email .
Lo stesso vale per tutti gli altri controlli dei moduli. Hai i pulsanti di opzione? Convalida rispetto all'elenco. Hai delle caselle di controllo? Convalida rispetto all'elenco. Hai un caricamento di file? Assicurarsi che il file sia del tipo previsto e trattare il nome file come dati utente non filtrati.
Ogni browser moderno viene fornito con un set completo di strumenti per sviluppatori integrato, il che rende banale per chiunque manipolare il tuo modulo. Il tuo codice dovrebbe presumere che l'utente abbia rimosso completamente tutte le restrizioni sul lato client sul contenuto del modulo !
Escaping dei dati per l'archiviazione
Ora che ti sei assicurato che i tuoi dati siano nel formato previsto e contengano solo i valori previsti, devi preoccuparti di conservare tali dati nella memoria.
Ogni singolo meccanismo di archiviazione dei dati ha un modo specifico per assicurarsi che i dati siano correttamente salvati e codificati. Se stai creando SQL, il modo accettato per passare i dati nelle query è attraverso istruzioni preparate con segnaposto .
Uno dei modi migliori per lavorare con la maggior parte dei database SQL in PHP è l' estensione PDO . Segue il modello comune di preparazione di un'istruzione , associazione delle variabili all'istruzione , quindi invio dell'istruzione e delle variabili al server . Se non hai mai lavorato con PDO prima, ecco un tutorial orientato a MySQL piuttosto buono .
Alcuni database SQL hanno le loro estensioni speciali in PHP, tra cui SQL Server , PostgreSQL e SQLite 3 . Ognuna di queste estensioni ha preparato il supporto delle istruzioni che opera nello stesso modo preparazione-esecuzione-rilegatura del PDO. A volte potrebbe essere necessario utilizzare queste estensioni anziché PDO per supportare funzionalità o comportamenti non standard.
MySQL ha anche le sue estensioni PHP. Due di loro, in effetti. Vuoi usare sempre solo quello chiamato mysqli . La vecchia estensione "mysql" è stata deprecata e non è sicura o sana da usare nell'era moderna.
Personalmente non sono un fan di mysqli. Il modo in cui esegue l'associazione variabile su dichiarazioni preparate non è flessibile e può essere una seccatura da usare. In caso di dubbi, utilizzare invece DOP.
Se non si utilizza un database SQL per archiviare i dati, consultare la documentazione per l'interfaccia del database in uso per determinare come passare i dati in modo sicuro attraverso di esso.
Quando possibile, assicurarsi che il database memorizzi i dati in un formato appropriato. Memorizza i numeri in campi numerici. Memorizza le date nei campi data. Conservare i soldi in un campo decimale, non in un campo a virgola mobile. Rivedere la documentazione fornita dal database su come archiviare correttamente diversi tipi di dati.
Escaping dei dati per la presentazione
Ogni volta che mostri dati agli utenti, devi assicurarti che i dati siano salvati in modo sicuro, a meno che tu non sappia che non dovrebbero essere salvati.
Quando si emette HTML, è necessario passare quasi sempre tutti i dati originariamente forniti dall'utente htmlspecialchars
. In effetti, l'unica volta che non dovresti farlo è quando sai che l'utente ha fornito HTML e che sai che è già stato disinfettato usando una whitelist.
A volte è necessario generare alcuni Javascript utilizzando PHP. Javascript non ha le stesse regole di escape dell'HTML! Un modo sicuro per fornire valori forniti dall'utente a Javascript tramite PHP è attraverso json_encode
.
E altro ancora
Esistono molte altre sfumature nella convalida dei dati.
Ad esempio, la codifica del set di caratteri può essere un'enorme trappola . La tua applicazione dovrebbe seguire le pratiche descritte in " UTF-8 fino in fondo ". Esistono attacchi ipotetici che possono verificarsi quando si trattano i dati di stringa come un set di caratteri errato.
In precedenza ho menzionato gli strumenti di debug del browser. Questi strumenti possono anche essere utilizzati per manipolare i dati dei cookie. I cookie devono essere trattati come input dell'utente non attendibile .
La convalida e l'escape dei dati sono solo un aspetto della sicurezza delle applicazioni web. È necessario essere consapevoli delle metodologie di attacco delle applicazioni Web in modo da poter creare difese contro di esse.