Dans le didacticiel d’aujourd’hui, nous allons apprendre à protéger votre application CodeIgniter (antérieure à 2.0) sans douleur et de manière efficace contre les attaques par falsification de requêtes entre sites. La bibliothèque que nous allons créer aujourd'hui automatisera tous les mécanismes de protection, ce qui renforcera la sécurité de votre site..
Les attaques de contrefaçon de requêtes entre sites sont basées sur des formulaires non protégés sur vos sites..
Un attaquant pourrait créer un faux formulaire sur son site, par exemple un formulaire de recherche. Ce formulaire peut avoir des entrées cachées contenant des données malveillantes. À présent, le formulaire n'est pas envoyé au site de l'attaquant pour effectuer la recherche. en réalité, la forme pointe vers votre site! Puisque votre site Web aura confiance en l'authenticité du formulaire, il exécute et exécute les actions demandées (et peut-être même malveillantes)..
Imaginez qu'un utilisateur soit connecté à votre site et soit redirigé vers le site de l'attaquant pour une raison quelconque (phishing, XSS, vous le nommez). Le formulaire de l'attaquant pourrait pointer sur le formulaire de suppression de votre compte sur votre site. Si l'utilisateur effectue une "recherche" sur le site de l'attaquant, son compte sera alors supprimé à son insu.!
Il existe de nombreux moyens de prévenir ces attaques..
POSTER
request, comparez le jeton soumis à celui du magasin et, s’ils diffèrent, refusez la demande. Votre site doit toujours être protégé contre XSS, car sinon, cette méthode devient inutile..Nous devrons faire trois choses pour chaque demande:
POSTER
demander, valider que le jeton soumis. Pour faire cela automatiquement, nous utiliserons les crochets CodeIgniter. Les crochets nous permettent d'exécuter toutes les actions sur différentes parties de la demande. Nous aurons besoin de trois:
Commençons. Nous allons procéder étape par étape afin de tout expliquer le plus précisément possible. Nous allons créer la méthode qui génère le jeton en premier afin de pouvoir tout tester correctement par la suite. Créez un fichier dans votre système / application / crochets
dossier appelé "csrf.php
"et collez le code suivant:
CI = & get_instance ();
Espérons que ce que nous avons ajouté ci-dessus devrait vous paraître plutôt fondamental. Nous créons une classe, appelée CSRF_Protection
, une variable d'instance pour contenir l'occurrence CodeIgniter, deux variables statiques pour contenir le nom du paramètre qui stockera le jeton et une pour stocker le jeton lui-même afin de faciliter l'accès à l'ensemble de la classe. Dans le constructeur de classe (__construction
), nous récupérons simplement l'instance CodeIgniter et la stockons dans notre variable d'instance correspondante.
Remarque: Le "nom du paramètre" est le nom du champ qui contient le jeton. Donc sur les formulaires, c'est le nom de l'entrée cachée.
Après le constructeur de la classe, collez le code suivant:
/ ** * Génère un jeton CSRF et le stocke en session. Un seul jeton par session est généré. * Cela doit être lié à un hook post-contrôleur, et avant le hook * qui appelle la méthode inject_tokens (). * * @return void * @author Ian Murray * / fonction publique generate_token () // Charge la bibliothèque de session si elle n'est pas chargée $ this-> CI-> load-> bibliothèque ('session'); if ($ this-> CI-> session-> userdata (self :: $ nom_poste) === FAUX) // Génère un jeton et le stocke en session, car l'ancien semble avoir expiré. self :: $ token = md5 (uniqid (). microtime (). rand ()); $ this-> CI-> session-> set_userdata (self :: $ token_name, self :: $ token); else // Définissez la variable locale pour un accès facile self :: $ token = $ this-> CI-> session-> userdata (self :: $ token_name);
Pas à pas:
FAUX
, alors le jeton n'est pas encore présent. Nous devons nous assurer que le jeton a été soumis et qu'il est valide si la demande est une requête. POSTER
demande. Allez-y et collez le code suivant dans votre csrf.php
fichier:
/ ** * Valide un jeton soumis lorsque la demande POST est faite. * * @return void * @author Ian Murray * / fonction publique validate_tokens () // S'agit-il d'une demande de publication? if ($ _SERVER ['REQUEST_METHOD'] == 'POST') // Le champ de jeton est-il défini et valide? $ posted_token = $ this-> CI-> input-> post (self :: $ token_name); if ($ posted_token === FALSE || $ posted_token! = $ this-> CI-> session-> userdata (self :: $ token_name)) // Requête non valide, erreur d’envoi 400. show_error ('Requête non valide. Les jetons ne correspondaient pas. ', 400);
POSTER
demande, ce qui signifie qu’un formulaire a effectivement été soumis. Nous vérifions cela en jetant un coup d’œil au REQUEST_METHOD
dans le $ _SERVER
super global. $ this-> CI-> input-> post (self :: $ token_name)
est FAUX
, alors le jeton n'a jamais été posté. C'est la partie amusante! Nous devons injecter les jetons sous toutes leurs formes. Pour nous faciliter la vie, nous allons placer deux balises méta dans notre (Rails-like). De cette façon, nous pouvons également inclure le jeton dans les requêtes AJAX..
Ajoutez le code suivant à votre csrf.php
fichier:
/ ** * Ceci injecte des balises masquées sur tous les formulaires POST avec le jeton csrf. * Injecte également des en-têtes méta dans de sortie (le cas échéant) pour un accès facile * depuis les frameworks JS. * * @retour void * @author Ian Murray * / fonction publique inject_tokens () $ output = $ this-> CI-> output-> get_output (); // Injecte dans le formulaire $ output = preg_replace ('/ (<(form|FORM)[^>] * (method | METHOD) = "(post | POST)" [^>] *>) / ',' $ 0', $ output); // Inject dans $ output = preg_replace ('/ (<\/head>) / ',''. "\ n". ''. "\ n". '$ 0', $ sortie); $ this-> CI-> output -> _ display ($ output);
display_override
hook, nous devons récupérer la sortie générée à partir de CodeIgniter. Nous faisons cela en utilisant le $ this-> CI-> output-> get_output ()
méthode. POSTER
. entête
(si présent). C’est simple, puisque la balise de tête de fermeture ne doit être présente qu’une fois par fichier.. display_override
hook, la méthode par défaut pour afficher votre vue ne sera pas appelée. Cette méthode inclut toutes sortes de choses, ce que nous ne devrions pas, uniquement pour injecter du code. L'appeler nous-mêmes résout ce problème. Dernier point, mais non le moindre, nous devons créer les hooks eux-mêmes - ainsi nos méthodes sont appelées. Collez le code suivant dans votre système / application / config / hooks.php
fichier:
// // Crochets de protection CSRF, ne les touchez pas sauf si vous savez ce que vous // faites. // // L'ORDRE DE CES CROCHETS EST EXTREMEMENT IMPORTANT! // // CECI DOIT ÊTRE PREMIÈREMENT DANS LA LISTE DE CROCHETS post_controller_constructor. $ hook ['post_controller_constructor'] [] = array (// Attention au "[]", ce n'est pas le seul hook post_controller_constructor 'class' => 'CSRF_Protection', 'function' => 'validate_tokens', 'nomfichier' = > 'csrf.php', 'filepath' => 'crochets'); // Génère le jeton (DOIT ARRIVER APRÈS QUE LA VALIDATION A ÉTÉ EFFECTUÉE, MAIS AVANT LE CONTRÔLEUR // EST EXÉCUTÉ, L'UTILISATEUR N'A AUCUN ACCÈS À UN JETON VALIDE POUR DES FORMULES PERSONNALISÉES). $ hook ['post_controller_constructor'] [] = array (// Attention au "[]", ce n'est pas le seul hook post_controller_constructor 'class' => 'CSRF_Protection', 'fonction' => 'generate_token', 'nomfichier' = > 'csrf.php', 'filepath' => 'crochets'); // Ceci injecte des jetons sur toutes les formes $ hook ['display_override'] = array ('class' => 'CSRF_Protection', 'function' => 'inject_tokens', 'filename' => 'csrf.php', 'filepath' => 'crochets');
post_controller_constructor
crochet, nous devons donc ajouter ces crochets ("[]
"). Reportez-vous à la documentation sur les crochets CodeIgniter pour plus d'informations.. post_controller_constructor
, génère le jeton s'il n'a pas encore été généré. forme
et le entête
. Avec un minimum d'effort, nous avons construit une assez belle bibliothèque pour nous-mêmes.
Vous pouvez utiliser cette bibliothèque dans n’importe quel projet, ce qui protégera automatiquement votre site contre CSRF..
Si vous souhaitez contribuer à ce petit projet, merci de laisser un commentaire ci-dessous ou de préciser le projet sur GitHub. Alternativement, à partir de CodeIgniter v2.0, la protection contre les attaques CSRF est désormais intégrée au framework.!