La sicurezza è un argomento caldo. Garantire che i siti Web siano sicuri è estremamente importante per qualsiasi applicazione web. In effetti, spendo il 70% del mio tempo per proteggere le mie applicazioni. Una delle cose più importanti che dobbiamo proteggere sono le forme. Oggi esamineremo un metodo per prevenire l'XSS (Cross-site scripting) e la falsificazione delle richieste tra siti nei moduli.
I dati POST possono essere inviati da un sito Web a un altro. Perché questo è cattivo? Uno scenario semplice ...
Un utente, registrato nel tuo sito web, visita un altro sito durante la sua sessione. Questo sito Web sarà in grado di inviare dati POST al tuo sito Web, ad esempio con AJAX. Poiché l'utente ha effettuato l'accesso sul tuo sito, l'altro sito Web sarà anche in grado di inviare i dati dei post a moduli protetti accessibili solo dopo un accesso.
Dobbiamo anche proteggere le nostre pagine dagli attacchi usando cURL
Con i tasti modulo! Aggiungeremo un hash speciale (una chiave del modulo) in ogni modulo per garantire che i dati vengano elaborati solo quando sono stati inviati dal tuo sito web. Dopo l'invio di un modulo, il nostro script PHP convaliderà la chiave del modulo inviato contro la chiave del modulo che abbiamo impostato in una sessione.
Per prima cosa abbiamo bisogno di un modulo semplice a scopo dimostrativo. Una delle forme più importanti da proteggere è il modulo di accesso. Il modulo di accesso è vulnerabile agli attacchi tobrute force. Crea un nuovo file e salvalo come index.php nella tua web-root. Aggiungi il seguente codice all'interno del corpo:
Proteggere i moduli con i tasti del modulo
Ora abbiamo una semplice pagina XHTML con un modulo di accesso. Se si desidera utilizzare le chiavi del modulo sul proprio sito Web, è possibile sostituire lo script in alto con la propria pagina di accesso. Ora, continuiamo con la vera azione.
Creeremo una classe PHP per le nostre chiavi di forma. Perché ogni pagina può contenere solo uno forma chiave, potremmo fare un singleton della nostra classe per assicurarci che la nostra classe sia utilizzata correttamente. Poiché la creazione di singleton è un argomento OOP più avanzato, salteremo questa parte. Crea un nuovo file chiamato formkey.class.php e posizionalo nella tua web-root. Ora dobbiamo pensare alle funzioni di cui abbiamo bisogno. Innanzitutto, abbiamo bisogno di una funzione per generare una chiave di forma in modo che possiamo inserirla nella nostra forma. Nel tuo file PHP inserisci il seguente codice:
Sopra, vedi una classe con tre parti: due variabili e una funzione. Rendiamo la funzione privata perché questa funzione verrà utilizzata solo dal nostro produzionefunzioni, che creeremo in seguito. Nelle due variabili, memorizzeremo le chiavi del modulo. Anche questi sono privati perché possono essere usati solo da funzioni all'interno della nostra classe.
Ora, dobbiamo pensare a un modo per generare la nostra chiave di forma. Poiché la nostra chiave di forma deve essere unica (altrimenti non abbiamo alcuna sicurezza), usiamo una combinazione di indirizzo IP dell'utente per associare la chiave a un utente, mt_rand () per renderla unica e la funzione uniqid () per renderlo ancora più unico. Inoltre, crittografiamo queste informazioni con md5 () per creare un hash univoco che possiamo quindi inserire nelle nostre pagine. Poiché abbiamo usato md5 (), un utente non può vedere cosa abbiamo usato per generare la chiave. L'intera funzione:
// Funzione per generare la funzione privata key form generateKey () // Ottieni l'indirizzo IP dell'utente $ ip = $ _SERVER ['REMOTE_ADDR']; // Usiamo mt_rand () invece di rand () perché è meglio per generare numeri casuali. // Usiamo 'true' per ottenere una stringa più lunga. // Vedi http://www.php.net/mt_rand per una descrizione precisa della funzione e altri esempi. $ uniqid = uniqid (mt_rand (), true); // Restituisce l'hash return md5 ($ ip. $ Uniqid);
Inserisci il codice sopra nel tuo formkey.class.php file. Sostituisci la funzione con la nuova funzione.
Per questo passaggio, creiamo una nuova funzione che genera un campo HTML nascosto con la nostra chiave del modulo. La funzione consiste di tre passaggi:
Diamo un nome alla nostra funzione outputKey () e renderlo pubblico, perché dobbiamo usarlo al di fuori della nostra classe. La nostra funzione chiamerà la funzione privata generateKey () per generare una nuova chiave del modulo e salvarla localmente in una sessione. Infine, creiamo il codice XHTML. Ora aggiungi il seguente codice all'interno della nostra classe PHP:
// Funzione per l'output della chiave di forma public function outputKey () // Genera la chiave e la memorizza nella classe $ this-> formKey = $ this-> generateKey (); // Salva la chiave del modulo nella sessione $ _SESSION ['form_key'] = $ this-> formKey; // Emette la chiave del modulo echo "formKey. "" /> ";
Ora, aggiungeremo la chiave del modulo al nostro modulo di accesso per proteggerlo. Dobbiamo includere la classe nel nostro index.php file. Dobbiamo anche avviare la sessione perché la nostra classe utilizza le sessioni per memorizzare la chiave generata. Per questo, aggiungiamo il seguente codice sopra il doctype e il tag head:
Il codice sopra è abbastanza auto-esplicativo. Iniziamo la sessione (perché memorizziamo la chiave del modulo) e cariciamo il file di classe PHP. Dopodiché, iniziamo la lezione con nuovo formKey (), questo creerà la nostra classe e la immagazzineremo $ formkey. Ora dobbiamo solo modificare il nostro modulo in modo che contenga la chiave del modulo:
E questo è tutto! Perché abbiamo creato la funzione outputKey (), dobbiamo solo includerlo nella nostra forma. Possiamo usare le chiavi del modulo in ogni forma semplicemente aggiungendo outputKey (); ?> Ora basta rivedere la fonte della tua pagina web e puoi vedere che c'è una chiave del modulo allegata al modulo. L'unico passo rimanente è la convalida delle richieste.
Non convalideremo l'intero modulo; solo la chiave del modulo. La convalida del modulo è di base PHP e le esercitazioni possono essere trovate in tutto il web. Convalidiamo la chiave del modulo. Poiché la nostra funzione "generateKey" sovrascrive il valore della sessione, aggiungiamo un costruttore alla nostra classe PHP. Un costruttore verrà chiamato quando la nostra classe viene creata (o costruita). Il costruttore memorizzerà la chiave precedente all'interno della classe prima ne creiamo uno nuovo; quindi avremo sempre la chiave del modulo precedente per la convalida del nostro modulo. Se non lo facessimo, non saremmo in grado di convalidare la chiave del modulo. Aggiungi la seguente funzione PHP alla tua classe:
// Il costruttore memorizza la chiave del modulo (se ne esiste una) nella nostra variabile di classe. function __construct () // Abbiamo bisogno della chiave precedente quindi la memorizziamo if (isset ($ _ SESSION ['form_key'])) $ this-> old_formKey = $ _SESSION ['form_key'];
Un costruttore dovrebbe sempre essere nominato __costruire(). Quando viene chiamato il costruttore, controlliamo se è stata impostata una sessione e, in tal caso, la memorizziamo localmente nel nostro old_formKey variabile.
Ora siamo in grado di convalidare la nostra chiave del modulo. Creiamo una funzione di base all'interno della nostra classe che convalida la chiave del modulo. Questa funzione dovrebbe anche essere pubblica perché la useremo al di fuori della nostra classe. La funzione convaliderà il valore POST della chiave del modulo rispetto al valore memorizzato della chiave del modulo. Aggiungi questa funzione alla classe PHP:
// Funzione che ha convalidato la chiave del form POST data public function validate () // Usiamo il vecchio formKey e non la nuova versione generata if ($ _ POST ['form_key'] == $ this-> old_formKey) // The la chiave è valida, restituisce true. ritorna vero; else // La chiave non è valida, restituisce false. restituisce falso;
Entro index.php, convalidiamo la chiave del modulo utilizzando la funzione appena creata nella nostra classe. Ovviamente, convalidiamo solo dopo una richiesta POST. Aggiungi il seguente codice dopo $ formKey = new formKey ();
$ error = 'Nessun errore'; // è richiesta? if ($ _ SERVER ['REQUEST_METHOD'] == 'post') // Convalidare la chiave del modulo if (! isset ($ _ POST ['form_key']) ||! $ formKey-> validate ()) // Form la chiave non è valida, mostra un errore $ error = 'Errore chiave form!'; else // Fai il resto della convalida qui $ error = 'Nessun errore nella chiave del form!';
Abbiamo creato una variabile $ error che memorizza il nostro messaggio di errore. Se è stata inviata una richiesta POST, convalidare la nostra formkey con $ FormKey-> validate (). Se restituisce false, la chiave del modulo non è valida e viene visualizzato un errore. Tieni presente che convalidiamo solo la chiave del modulo: devi convalidare il resto del modulo da solo.
Nel tuo codice HTML, puoi inserire il seguente codice per mostrare il messaggio di errore:
Questo farà eco al $ error variabile se è impostata.
Se avvii il tuo server e vai a index.php, vedrai il nostro modulo e il messaggio "Nessun errore". Quando invii un modulo, visualizzerai il messaggio "Nessun errore chiave del modulo" perché è una richiesta POST valida. Ora prova a ricaricare la pagina e accetta quando il tuo browser richiede di inviare nuovamente i dati POST. Vedrai che il nostro script attiva un messaggio di errore: "Errore chiave form!" Il tuo modulo è ora protetto da input provenienti da altri siti Web e errori con ricariche di pagine! L'errore viene anche visualizzato dopo un aggiornamento perché è stata generata una nuova chiave del modulo dopo che abbiamo inviato il modulo. Ciò è positivo perché, ora, l'utente non può inserire per errore un modulo due volte.
Ecco l'intero codice PHP e HTML:
index.php
validate ()) // La chiave del modulo non è valida, mostra un errore $ error = 'Errore chiave del form!'; else // Fai il resto della convalida qui $ error = 'Nessun errore nella chiave del form!'; ?>Proteggere i moduli con i tasti del modulo fomrkey.class.php
old_formKey = $ _SESSION ['form_key']; // Funzione per generare la funzione privata della chiave del modulo generateKey () // Ottieni l'indirizzo IP dell'utente $ ip = $ _SERVER ['REMOTE_ADDR']; // Usiamo mt_rand () invece di rand () perché è meglio per generare numeri casuali. // Usiamo 'true' per ottenere una stringa più lunga. // Vedi http://www.php.net/mt_rand per una descrizione precisa della funzione e altri esempi. $ uniqid = uniqid (mt_rand (), true); // Restituisce l'hash return md5 ($ ip. $ Uniqid); // Funzione per l'output della chiave di forma public function outputKey () // Genera la chiave e la memorizza nella classe $ this-> formKey = $ this-> generateKey (); // Salva la chiave del modulo nella sessione $ _SESSION ['form_key'] = $ this-> formKey; // Emette la chiave del modulo echo "formKey. "" /> "; // Funzione che ha convalidato la chiave del modulo POST data public function validate () // Usiamo il vecchio formKey e non la nuova versione generata if ($ _ POST ['form_key'] == $ this-> old_formKey) // La chiave è valida, restituisce true. return true; else // La chiave non è valida, restituisce false. restituisce false;?>Conclusione
L'aggiunta di questo codice a ogni modulo importante sul tuo sito web aumenterà drasticamente la sicurezza del tuo modulo. Arresta anche i problemi di aggiornamento, come abbiamo visto nel passaggio 4. Poiché la chiave del modulo è valida solo per una richiesta, non è possibile un doppio post.
Questo è stato il mio primo tutorial, spero che ti piaccia e usalo per migliorare la tua sicurezza! Per favore fatemi sapere i vostri pensieri, tramite i commenti. Hai un metodo migliore? Facci sapere.
Ulteriori letture
- WordPress utilizza anche i tasti modulo (denominandolo Nonces): Wordpress Nonces
- Sette abitudini per scrivere applicazioni PHP sicure
- Seguici su Twitter o iscriviti al feed RSS di NETTUTS per ulteriori tuts e articoli di sviluppo web giornalieri.