PHP : Protection contre l'injection de code

29 septembre 2013 rdorigny 0 commentaires

L'OWASP (Open Web Application Security Project) est une communauté travaillant sur la sécurité des applications Web. Elle publie régulièrement le top dix des risques de sécurité applicatifs web les plus critiques. Ce classement fait référence aujourd'hui dans le domaine de la sécurité et est cité par divers organismes (DoD, PCI Security Standard).

Le risque le plus critique, et le plus souvent utilisé sur des sites vulnérables, est l'injection de code qui existe sous de multiples formes (SQL, XSS, ...).

Voici un article pour vous aider à protéger vos pages PHP contre ce fléau.

1) Qu'est ce que l'injection de code?

L'injection de code est une technique qui consiste à injecter des données dans une application pour en modifier le comportement ou se donner des droits sur l'applicatif.

Comment réaliser une injection?
Souvent, les pages vulnérables sont celles qui affichent le retour d'un formulaire.
Un exemple simple consiste à injecter du code javascript :
'<script>alert();</script>


La fenêtre ci-dessus s'affiche. Explication, la côte comme premier caractère a clôturé proprement la balise input du formulaire html, ensuite nous avons un script javascript qui n'affiche rien et attend une validation de l'utilisateur pour continuer.

Un autre exemple très connu est l'injection SQL. Nous allons prendre l'exemple d'un formulaire de connexion à un site web. L'usager doit en théorie taper son login et son password. Une implémentation basique de ce mécanisme consiste à tester la base de données des abonnés en utilisant une requête SQL de la forme :
SELECT uid FROM Users WHERE name = 'Dupont' AND password = '45723a2af3788c4ff17f8d1114760e62';


L'attaquant connait ce mécanisme de connexion est présuppose que la requête SQL est de cette forme. Il tape le login Dupont et tape pour mot passe le code : ' or 1=1 --. Ce qui donne:
SELECT uid FROM Users WHERE name = 'Dupont' AND password = '' or 1=1 --';

Le -- met en commentaire tout ce qui suit et le OR 1=1 permet à requête de retourner true systématiquement. Ainsi, l'attaquant court-circuite la validation du mot de passe et force la requête à renvoyer true.

Vous pouvez tester ces deux exemples sur votre site, et si cela réagit comme ci-dessus alors je vous conseille vivement d’appliquer ce qui va suivre!

2) Comment s'en protéger?

L'attaquant doit injecter son code, il faudra donc tester les entrées renvoyées par l'usager et supprimer les éléments dangereux comme certains caractères spéciaux et interdire certains mots qui pourrait être utilisé à des fins intrusives ou destructrices.

Le simple fait de retirer les caractères spéciaux et de limiter les entrées à quelques caractères bien définis va énormément compliquer la tâche de l'attaquant. Il lui sera quasi-impossible de passer au travers de cette restriction.

Pour les mots clés à supprimer, il faudra également être attentifs à ce que peut insérer l'attaquant car il y a des cas à prendre en

Imaginons que notre script de protection teste les entrées est supprime le mot SCRIPT, il y a deux attaques possibles pour bypasser cette limitation:
  • Si le test ne prend pas en compte la "casse" (minuscule/majuscule, il y a tout les chances pour que l'entrée ScrIpT ne soit pas supprimée. Et pourtant, elle aura le même effet que SCRIPT,
  • Une seconde façon d'attaquer est d'insérer un motif dans un motif. En reprenant l'exemple précédent, l'attaquant tapera scrscriptipt. Si le système de protection n'est pas itératif et ne refait pas un test après un nettoyage, alors cette attaque fera mouche!


  • Donc voici un script qui réalise la protection d'une page PHP. Bien évidement, ce script prend en compte les remarques citées supra.
    //************************************************************************************************ //filtre injection de code function Filtre_injection($tab) { //Blacklist des mots à supprimer $patern=array("UNION","SCRIPT","CREATE","UPDATE","INSERT","SELECT","WHERE","FLUSH","DROP","EXEC","ALTER", "TRUNCATE","DESTROY", "ORDER", "COUNT", "GROUP", "HAVING","UNION"); //Suppression des caractères spéciaux $tab=preg_replace("#[^a-zA-Z0-9:.éèçêë@ ]#", "", $tab); //Suppression des mots clés $t=array_keys($tab); foreach ($t as $value) { for ($i=0;$i<sizeof($patern);$i++) while (stristr($tab[$value],$patern[$i])) //Recherche itératif du motif pour gérer les injections du type <scr<script>ipt> $tab[$value]=str_ireplace($patern[$i],"",$tab[$value]); } unset($value); return($tab); } //Application de la protection d'injection dans les tableaux de variables $_COOKIE_2=array(); $_GET_2=array(); $_POST_2=array(); $_COOKIE_2=Filtre_injection($_COOKIE); $_GET_2=Filtre_injection($_GET); $_POST_2=Filtre_injection($_POST);


    Conclusion

    Vous pouvez vous baser sur cet exemple de script afin de sécuriser votre site. N'oubliez pas une chose importante, celle de bien identifier les vecteurs d'entrées/sorties de votre application. C'est par ces vecteurs que l'attaquant entrera, on peut lister l'url, les fichiers transmis, et les variables externes de PHP ($_GET, $_POST, $_COOKIE, ...).







    Pseudonyme (obligatoire) :
    Adresse mail (obligatoire) :
    Site web :




    © 2017 www.doritique.fr par Robert DORIGNY