In de tutorial van vandaag zullen we leren hoe je je CodeIgniter (pre 2.0) -toepassing pijnloos kunt beveiligen tegen Cross-Site Request Forgery-aanvallen. De bibliotheek die we vandaag zullen creëren, automatiseert alle beveiligingsmechanismen, waardoor uw site sterker en veiliger wordt.
Cross-Site Request Forgery-aanvallen zijn gebaseerd op onbeveiligde formulieren op uw sites.
Een aanvaller kan een valse vorm op zijn site maken, bijvoorbeeld een zoekformulier. Dit formulier kan verborgen ingangen bevatten die schadelijke gegevens bevatten. Nu wordt het formulier niet daadwerkelijk naar de site van de aanvaller gestuurd om de zoekopdracht uit te voeren; in werkelijkheid wijst de vorm naar jouw site! Omdat uw website erop vertrouwt dat het formulier echt is, doorloopt het de gevraagde (en misschien kwaadwillende) acties en voert het uit.
Stel je voor dat een gebruiker is ingelogd op je site en om een of andere reden wordt omgeleid naar de site van de aanvaller (phishing, XSS, noem maar op). Het formulier van de aanvaller kan naar uw accountverwijderingsformulier op uw site verwijzen. Als de gebruiker een "zoekopdracht" uitvoert op de site van de aanvaller, wordt zijn account vervolgens verwijderd zonder dat hij het weet!
Er zijn talloze manieren om dit soort aanvallen te voorkomen.
POST
verzoek, vergelijk het aangeleverde token met datgene dat in de winkel ligt en, als ze verschillen, het verzoek afwijzen. Uw site moet echter nog steeds worden beschermd tegen XSS, want als dit niet het geval is, wordt deze methode onbruikbaar.We moeten drie dingen doen voor elke aanvraag:
POST
aanvraag, valideer dat het ingediende token. Om dit automatisch te doen, zullen we CodeIgniter-haken gebruiken. Met haakjes kunnen we alle acties op verschillende delen van het verzoek uitvoeren. We hebben er drie nodig:
Laten we beginnen. We gaan stap voor stap om alles zo grondig mogelijk uit te leggen. We maken de methode die het token als eerste genereert, zodat we alles achteraf correct kunnen testen. Maak een bestand in uw system / application / hooks
map genaamd "csrf.php
"en plak de volgende code:
CI = & get_instance ();
Hopelijk is wat we hierboven hebben toegevoegd nogal basic voor u. We maken een klasse, genaamd CSRF_Protection
, een instantievariabele om de CodeIgniter-instantie te houden, twee statische variabelen die de naam bevatten van de parameter die het token opslaat, en één om het token zelf op te slaan voor eenvoudige toegang door de hele klas. Binnen de klassenbouwer (__construct
), halen we eenvoudig de CodeIgniter-instantie op en slaan deze op in onze overeenkomstige instantievariabele.
Notitie: De "naam van de parameter" is de naam van het veld dat het token bevat. Dus op de formulieren is dit de naam van de verborgen invoer.
Na de klassenconstructor plakt u de volgende code:
/ ** * Genereert een CSRF-token en slaat het op tijdens de sessie. Er wordt slechts één token per sessie gegenereerd. * Dit moet worden gekoppeld aan een haak na de controller en vóór de hook * die de methode inject_tokens () aanroept. * * @return void * @author Ian Murray * / public function generate_token () // Laad sessiebibliotheek indien niet geladen $ this-> CI-> laad-> bibliotheek ('sessie'); if ($ this-> CI-> session-> userdata (self :: $ token_name) === FALSE) // Genereer een token en sla deze op tijdens de sessie, omdat de oude lijkt te zijn verlopen. self :: $ token = md5 (uniqid (). microtime (). rand ()); $ this-> CI-> session-> set_userdata (self :: $ token_name, self :: $ token); else // Stel het in op lokale variabele voor eenvoudige toegang zelf :: $ token = $ this-> CI-> session-> userdata (self :: $ token_name);
Stap voor stap:
VALSE
, dan is het token nog niet aanwezig. We moeten ervoor zorgen dat het token is ingediend en is geldig in het geval dat het verzoek een is POST
verzoek. Ga je gang en plak de volgende code in je csrf.php
het dossier:
/ ** * Valideert een ingediend token wanneer een POST-aanvraag is gedaan. * * @return void * @author Ian Murray * / public function validate_tokens () // Is dit een postverzoek? if ($ _SERVER ['REQUEST_METHOD'] == 'POST') // Is het tokenveld ingesteld en geldig? $ placed_token = $ this-> CI-> input-> post (self :: $ token_name); if ($ posted_token === FALSE || $ posted_token! = $ this-> CI-> session-> userdata (self :: $ token_name)) // Ongeldig verzoek, verzendfout 400. show_error ('Verzoek was ongeldig. Tokens kwamen niet overeen. ', 400);
POST
aanvraag, wat betekent dat er in feite een formulier is ingediend. We controleren dit door een kijkje te nemen naar de REQUEST_METHOD
binnen de $ _SERVER
super globaal. $ This-> CI-> input-> post (zelf :: $ TOKEN_NAME)
is VALSE
, dan is het token nooit gepost. Dit is het leuke gedeelte! We moeten de tokens in alle vormen injecteren. Om ons leven gemakkelijker te maken, gaan we twee metatags in onze plaatsen (Rails-achtige). Op die manier kunnen we het token ook opnemen in AJAX-verzoeken.
Voeg de volgende code toe aan uw csrf.php
het dossier:
/ ** * Dit injecteert verborgen tags op alle POST-formulieren met het csrf-token. * Injecteert ook meta-headers in van uitvoer (indien aanwezig) voor eenvoudige toegang * vanuit JS-frameworks. * * @return void * @author Ian Murray * / public function inject_tokens () $ output = $ this-> CI-> output-> get_output (); // Injecteer in formulier $ output = preg_replace ('/ (<(form|FORM)[^>] * (methode | METHOD) = "(bericht | POST)" [^>] *>) / ',' $ 0', $ uitvoer); // Injecteer in $ output = preg_replace ('/ (<\/head>) / ',''. "\ n". ''. "\ n". '$ 0', $ uitvoer); $ This-> CI-> uitgang -> _ display ($ output);
display_override
haak, we moeten de gegenereerde uitvoer ophalen uit CodeIgniter. We doen dit door de $ This-> CI-> output-> get_output ()
methode. POST
. hoofd
(indien aanwezig). Dit is eenvoudig, omdat de tag voor de afsluitende kop slechts eenmaal per bestand aanwezig mag zijn. display_override
hook, de standaardmethode om uw weergave weer te geven, wordt niet aangeroepen. Deze methode omvat allerlei dingen, die we niet zouden moeten doen - alleen voor het doel van het injecteren van wat code. Als we het zelf noemen, lost dit dit op. Last but not least, we moeten zelf de hooks maken - dus onze methoden worden gebeld. Plak de volgende code in uw system / application / config / hooks.php
het dossier:
// // CSRF Beschermingshaken, raak deze alleen aan als u weet wat u // doet. // // DE ORDE VAN DEZE HAKEN IS EXTREEM BELANGRIJK !! // // DIT MOET EERST IN DE HAAKLIJST post_controller_constructor PLAATSEN. $ hook ['post_controller_constructor'] [] = array (// Let op de "[]", dit is niet de enige post_controller_constructor hook 'class' => 'CSRF_Protection', 'function' => 'validate_tokens', 'filename' = > 'csrf.php', 'filepath' => 'hooks'); // Genereert het token (MOET GEBEUREN NA DE VALIDERING IS GEMAAKT, MAAR VOORDAT DE CONTROLLER // WORDT UITGEVOERD, ANDERS HEEFT GEBRUIKER GEEN TOEGANG TOT EEN GELDIG TOKEN VOOR AANGEPASTE VORMEN). $ hook ['post_controller_constructor'] [] = array (// Let op de "[]", dit is niet de enige post_controller_constructor hook 'class' => 'CSRF_Protection', 'function' => 'generate_token', 'filename' = > 'csrf.php', 'filepath' => 'hooks'); // Dit injecteert tokens op alle vormen $ hook ['display_override'] = array ('class' => 'CSRF_Protection', 'function' => 'inject_tokens', 'filename' => 'csrf.php', 'filepath' => 'hooks');
post_controller_constructor
haak, dus we moeten die haakjes toevoegen ("[]
"). Raadpleeg de documentatie over CodeIgniter-hooks voor meer informatie. post_controller_constructor
, genereert het token in het geval het nog niet is gegenereerd. het formulier
en de hoofd
. Met minimale inspanning hebben we een aardige bibliotheek voor onszelf gebouwd.
U kunt deze bibliotheek gebruiken in elk project en het beschermt uw site automatisch tegen CSRF.
Als je wilt bijdragen aan dit kleine project, kun je hieronder een reactie achterlaten, of het project aanvullen op GitHub. Als alternatief, vanaf CodeIgniter v2.0, is nu bescherming tegen CSRF-aanvallen ingebouwd in het raamwerk!