Nel tutorial di oggi, impareremo come proteggere in modo indolore l'applicazione CodeIgniter (pre 2.0) contro gli attacchi di contraffazione di richieste tra siti. La libreria che creeremo oggi automatizzerà tutti i meccanismi di protezione, rendendo il tuo sito più forte e più sicuro.
Richiesta cross-site Gli attacchi di contraffazione sono basati su moduli non protetti sui tuoi siti.
Un utente malintenzionato potrebbe creare un modulo falso sul suo sito, ad esempio un modulo di ricerca. Questo modulo potrebbe contenere input nascosti contenenti dati dannosi. Ora il modulo non viene effettivamente inviato al sito dell'utente malintenzionato per eseguire la ricerca; in realtà, la forma punta a il tuo posto! Dal momento che il tuo sito Web si fida che il modulo è autentico, passa attraverso e esegue le azioni richieste (e forse anche quelle dannose).
Immagina che un utente abbia effettuato l'accesso al tuo sito e venga reindirizzato al sito dell'utente malintenzionato per qualche motivo (phishing, XSS, tu lo chiami). Il modulo del malintenzionato potrebbe indicare il modulo di eliminazione dell'account sul tuo sito. Se l'utente esegue una "ricerca" sul sito degli attaccanti, il suo account verrà eliminato senza che lui lo sappia!
Esistono numerosi modi per prevenire questo tipo di attacchi.
INVIARE
richiesta, confronta il token inviato con quello in negozio e, se sono diversi, rifiuta la richiesta. Il tuo sito deve comunque essere protetto contro XSS, perché se non lo è, questo metodo diventa inutile.Dovremo fare tre cose per ogni richiesta:
INVIARE
richiesta, convalidare il token inviato. Per farlo automaticamente, utilizzeremo gli hook CodeIgniter. Gli hook ci permettono di eseguire tutte le azioni su diverse parti della richiesta. Ne avremo bisogno tre:
Iniziamo. Andremo passo dopo passo per spiegare tutto nel modo più completo possibile. Creeremo il metodo che genera prima il token, quindi possiamo testare tutto correttamente in seguito. Crea un file nel tuo sistema / applicazione / ganci
cartella chiamata "csrf.php
"e incollare il seguente codice:
CI = & get_instance ();
Speriamo che ciò che abbiamo aggiunto sopra dovrebbe sembrare piuttosto di base per te. Stiamo creando una classe, chiamata csrf_protection
, una variabile di istanza per contenere l'istanza CodeIgniter, due variabili statiche per contenere il nome del parametro che memorizzerà il token e una per memorizzare il token stesso per un facile accesso all'intera classe. All'interno del costruttore della classe (__costruire
), recuperiamo semplicemente l'istanza CodeIgniter e la memorizziamo nella nostra variabile di istanza corrispondente.
Nota: Il "nome del parametro" è il nome del campo che contiene il token. Quindi sulle forme, è il nome dell'input nascosto.
Dopo il costruttore della classe, incolla il seguente codice:
/ ** * Genera un token CSRF e lo memorizza durante la sessione. Viene generato un solo token per sessione. * Questo deve essere legato a un hook post-controller e prima del hook * che chiama il metodo inject_tokens (). * * @return void * @author Ian Murray * / public function generare_token () // Carica la libreria di sessione se non caricata $ this-> CI-> load-> library ('session'); if ($ this-> CI-> session-> userdata (self :: $ token_name) === FALSE) // Genera un token e lo memorizza nella sessione, dal momento che quello vecchio sembra essere scaduto. self :: $ token = md5 (uniqid (). microtime (). rand ()); $ this-> CI-> session-> set_userdata (self :: $ token_name, self :: $ token); else // Impostalo sulla variabile locale per auto di facile accesso :: $ token = $ this-> CI-> session-> userdata (self :: $ token_name);
Passo dopo passo:
FALSE
, quindi il token non è ancora presente. Dobbiamo assicurarci che il token sia stato inviato ed è valido nel caso in cui la richiesta sia a INVIARE
richiesta. Vai avanti e incolla il seguente codice nel tuo csrf.php
file:
/ ** * Convalida un token inviato quando viene effettuata la richiesta POST. * * @return void * @author Ian Murray * / public function validate_tokens () // Questa è una richiesta? if ($ _SERVER ['REQUEST_METHOD'] == 'POST') // Il campo token è impostato e valido? $ posted_token = $ this-> CI-> input-> post (self :: $ token_name); if ($ posted_token === FALSE || $ posted_token! = $ this-> CI-> session-> userdata (self :: $ token_name)) // Richiesta non valida, invio errore 400. show_error ('Richiesta non valida. I token non corrispondevano. ', 400);
INVIARE
richiesta, il che significa che un modulo è stato, di fatto, presentato. Controlliamo questo dando un'occhiata al REQUEST_METHOD
all'interno del $ _SERVER
super globale. $ This-> CI-> input-> Post (self :: $ nome_token)
è FALSE
, quindi il token non è mai stato pubblicato. Questa è la parte divertente! Abbiamo bisogno di iniettare i token in tutte le forme. Per semplificarci la vita, inseriremo due meta tag all'interno del nostro (Rails-like). In questo modo, possiamo includere anche il token nelle richieste AJAX.
Aggiungi il seguente codice al tuo csrf.php
file:
/ ** * Inietta i tag nascosti su tutte le forme POST con il token csrf. * Inietta anche meta intestazioni in di output (se esiste) per un facile accesso * da framework JS. * * @return void * @author Ian Murray * / public function inject_tokens () $ output = $ this-> CI-> output-> get_output (); // Iniettare in forma $ output = preg_replace ('/ (<(form|FORM)[^>] * (metodo | METHOD) = "(post | POST)" [^>] *>) / ',' $ 0', $ output); // Iniettare in $ output = preg_replace ('/ (<\/head>) / ',''. "\ n". ''. "\ n". '$ 0', $ output); $ This-> CI-> uscita -> _ display ($ output);
display_override
hook, dobbiamo recuperare l'output generato da CodeIgniter. Lo facciamo usando il $ This-> CI-> output-> get_output ()
metodo. INVIARE
. intestazione
(se presente). Questo è semplice, dal momento che il tag head di chiusura dovrebbe essere presente solo una volta per file. display_override
hook, il metodo predefinito per visualizzare la vista non verrà chiamato. Questo metodo include tutti i tipi di cose, che non dovremmo - solo allo scopo di iniettare del codice. Chiamarlo noi stessi risolve questo. Ultimo, ma non meno importante, abbiamo bisogno di creare gli stessi hook - così vengono chiamati i nostri metodi. Incolla il seguente codice nel tuo system / application / config / hooks.php
file:
// // Hook di protezione CSRF, non toccarli a meno che tu non sappia cosa stai facendo //. // // L'ORDINE DI QUESTI GANCI È ESTREMAMENTE IMPORTANTE !! // // QUESTO DEVE ANDARE PRIMA NELLA LISTA DELL'ELENCO post_controller_constructor. $ hook ['post_controller_constructor'] [] = array (// Ricorda "[]", questo non è l'unico post_controller_constructor hook 'class' => 'CSRF_Protection', 'function' => 'validate_tokens', 'filename' = > 'csrf.php', 'filepath' => 'ganci'); // Genera il token (DEVE ACCADERE DOPO CHE LA VALIDAZIONE È STATA EFFETTUATA, MA PRIMA CHE IL CONTROLLER // È ESEGUITO, ALTRIMENTI L'UTENTE NON HA ACCESSO A UN GESTORE VALIDO PER LE FORME PERSONALIZZATE). $ hook ['post_controller_constructor'] [] = array (// Mind the "[]", questo non è l'unico post_controller_constructor hook 'class' => 'CSRF_Protection', 'function' => 'generate_token', 'filename' = > 'csrf.php', 'filepath' => 'ganci'); // Inietta token su tutte le forme $ hook ['display_override'] = array ('class' => 'CSRF_Protection', 'function' => 'inject_tokens', 'filename' => 'csrf.php', 'filepath' => 'ami');
post_controller_constructor
gancio, quindi abbiamo bisogno di aggiungere quelle parentesi ("[]
") Per ulteriori informazioni, consultare la documentazione sui ganci CodeIgniter. post_controller_constructor
, genera il token nel caso in cui non sia stato ancora generato. modulo
e il intestazione
. Con il minimo sforzo, abbiamo creato una libreria piuttosto bella per noi stessi.
Puoi utilizzare questa libreria in qualsiasi progetto e proteggerà automaticamente il tuo sito contro CSRF.
Se desideri contribuire a questo piccolo progetto, ti preghiamo di lasciare un commento qui sotto, oppure inserire il progetto su GitHub. In alternativa, a partire da CodeIgniter v2.0, la protezione dagli attacchi CSRF è ora integrata nel framework!