NOUVEAUTéS Sécurité des scripts php / SQL

La sécurité Web: vue d’ensemble.


Que votre site soit celui d’une grande multinationale, d’une galerie commerciale mettant en avant votre gamme de produits à de clients potentiels les invitant à venir acheter dans la boutique, ou un site institutionnel présentant votre entreprise, il se pose des questions de sécurité sur Internet.
Après le travail acharné pour rendre votre site attrayant et répondre aux besoins de vos utilisateurs, c’est bien la dernière chose que vous souhaitez qu’un hacker malveillant vienne, effectuer un hack PHP et le casser d’une façon ou d’un autre.

Il y a un certain nombre de problèmes en matière de sécurité web, et, malheureusement, ils n’ont pas tous de solutions définitives, mais nous allons ici étudier certains des problèmes qui devraient être considérés à chaque fois que vous vous apprêtez à écrire un script PHP pour éviter qu’une faille PHP se produise. Ce sont les problèmes qui, avec un code bien conçu, peut être complètement éliminé. Avant d'examiner en détail les solutions, prenons un moment pour définir le fond du problème.

Injection SQL
Dans ce type d’attaque, l'utilisateur est en mesure d'exécuter des requêtes SQL dans la base de données de votre site web. Cette attaque est généralement effectuée par la saisie de texte dans un champ de formulaire qui provoque une requête SQL, générée par le code de traitement de formulaires PHP pour exécuter une partie du contenu du champ de formulaire comme si c'était du SQL autorisé.
Les effets et les conséquences de ces attaques sont loin d’être inoffensifs (en utilisant SELECT pour extraire un ensemble de données) voir dévastatrices (suppression de la base de données, par exemple). Dans les attaques plus subtiles, les données peuvent être modifiées, ou subtilisées par de nouvelles données fictives.

 

Traversée des Répertoires (Directory Traversal)
Cette attaque peut se produire n'importe où les données fournies par l'utilisateur (à partir d'un champ de formulaire ou d'un fichier téléchargé, par exemple) sont utilisées par une opération de système de fichiers. Si un utilisateur spécifie ".. /.. /.. /.. /.. /.. / Etc / passwd" en tant que données de formulaire et vos ajoute de script à un nom de répertoire pour obtenir des fichiers spécifiques à un utilisateur, cette chaîne pouvait conduire à la récupération immédiate du contenu du fichier de mot de passe, au lieu de le fichier voulu. Les cas plus graves concernent les opérations telles que le déplacement et la suppression de fichiers, qui permettent à un attaquant de faire des changements arbitraires de la structure de votre système de fichiers.

 

Problèmes d'authentification
Problèmes d'authentification donnent à des utilisateurs illégitimes accès à un contenu protégé, mais permis à d'autres utilisateurs légitimes. Un exemple serait un utilisateur qui a réussi à voler (ou construire) un cookie leur permettant de se connecter à votre site sous une session administrateur, et donc être en mesure de changer tout ce qu’ils souhaitent alors qu’ils n’en ont pas le droit.

 

Lancement de Scripts à distance (XSS)
XSS ou cross-site scripting (aussi parfois appelé CSS, à ne pas confondre avec le Cascading Style Sheets), est le processus d’exploitation d'une faille de sécurité dans un site qui permet d’exécuter du code arbitraire sur le serveur de ce site. Le code est généralement inclus dans un script PHP en cours d'exécution à partir d'un emplacement distant. Il s'agit d'une grave attaque critique qui pourrait permettre à un code que l'attaquant choisit pour être exécuté sur le serveur vulnérable, avec toutes les autorisations de l'utilisateur hébergeant le script, y compris sur les bases de données et sur l'accès du système de fichiers.

 

Traitement des données utilisateur - Formulaire d'entrée vérification et affichage HTML

Entrée/ validation et découverte des Balises
Quand un utilisateur entre des informations dans des formulaires qui doit être traités ultérieurement sur votre site, ils ont le pouvoir d'entrer dans tout ce qu'ils veulent. Le code qui traite l'entrée de formulaire doit être rédigé avec soin pour s'assurer que l'entrée de la saisie est correcte; champs de mot de passe ont le niveau de complexité requis, les champs e-mail ont au moins quelques caractères, par exemple, un signe @, certains autres caractères, d'un point (du site web), et deux ou plus de caractères à la fin, le code zip ou les codes postaux sont du format requis, et ainsi de suite…

Chacun d'entre eux peut être vérifiés en utilisant des expressions régulières, qui analysent la saisie suivant certains modèles. Un exemple pour la vérification des adresses e-mail est le code PHP ci-dessous. Le résultat est positif si une adresse e-mail a été entré dans le champ nommé 'email'.

 

preg_match ('/ ^ + @ + \ .. {2,3} $ /..', $ _POST ['email']);

 

Ce code construit juste une expression régulière basée sur le format décrit ci-dessus pour une adresse e-mail. Notez que cela est vrai pour n'importe quoi avec un signe @ et un point suivi par 2 ou 3 caractères. C'est le format général d'une adresse e-mail, mais cela ne signifie pas que l'adresse existe nécessairement, vous aurez besoin d’envoyer du courrier au destinataire pour être sûr que l’email est valide.

Comment cela est-il lié à la sécurité du site web?
Eh bien, pensez à un livre d'or à titre d'exemple. Ici, les utilisateurs sont invités à entrer un message dans un formulaire, qui est ensuite affiché sur la page HTML avec des commentaires de tout le monde. Pour l'instant, nous n'allons pas entrer dans les questions de sécurité de base de données, les problèmes traités ci-dessous peuvent se produire si les données sont stockées dans une base de données, un fichier ou autre.

Si un utilisateur entre des données qui contient des balises HTML, ou même JavaScript, puis lorsque les données sont incluses dans votre code HTML un affichage ultérieur, leur code HTML ou JavaScript ser aussi intégré.

Si votre page s'affiche livre d'or tout ce qui était entré dans le champ de formulaire, l'utilisateur a entré par exemple :

Salut, j’ <b> aime </ b> votre site.

Ensuite, l'effet est minime, lorsqu'elles sont affichées plus tard, cela semblerait que,

Salut, j'aime votre site.

Bien sûr, lorsque l'utilisateur saisit du JavaScript, les choses peuvent devenir bien pire. Par exemple, les données ci-dessous, une fois entré dans un formulaire qui n'empêche pas le JavaScript se retrouvera dans la page finale, causeront à la page une redirection vers un autre site Web. Évidemment, cela ne fonctionne que si le client a activé Javascript dans son navigateur, mais la grande majorité des utilisateurs ont javascript activé par défaut.

Salut, j'aime votre site. GEANT! <Script de
language = "JavaScript"> document.location = "http://www.acunetix.com/"; </ script>

Pour une fraction de seconde lorsque ce message est affiché, l'utilisateur verra,

Salut, j'aime votre site. GEANT!

Le navigateur va alors intervenir et la page sera rafraîchie à partir de www.acunetix.com. Dans ce cas, une page alternative assez inoffensive, même si elle ne se traduit pas par une attaque par déni de service, les utilisateurs ne peuvent plus se rendre à votre livre d'or...et il y a un détournement de trafic !

Prenons un cas où cela a été fait dans un formulaire de commande en ligne. Votre gestionnaire de commande ne seraient pas en mesure d'afficher les données parce que chaque fois qu'ils vont essayer, leur navigateur sera redirigé vers un autre site. Pire encore, si la redirection a eu lieu sur une page essentielle pour une grande entreprise, ou la redirection était à un site contenant du matériel répréhensible, des commandes peuvent être perdues à la suite de l'attaque.

Heureusement, PHP fournit un moyen de prévenir ce type d’attaque PHP. Les fonctions strip_tags (), nl2br () et htmlspecialchars () sont tes amis, ici.

strip_tags () supprime toutes les balises PHP ou HTML à partir d'une chaîne. Cela évite les problèmes d'affichage HTML, l'exécution JavaScript (la balise <script> sera détruite) et une variété de problèmes vont disparaitre afin que le code PHP puisse être exécuté normalement.

nl2br () convertit les caractères de nouvelle ligne dans l'entrée <br /> balises HTML. Cela vous permet de formater entrée multi-ligne correctement, et est mentionné ici parce qu'il est important d'exécuter strip_tags () avant d'exécuter nl2br () sur vos données, sinon les balises <br /> nouvellement insérés seront éliminés, lorsque strip_tags () est lancé!

Enfin, htmlspecialchars () seront caractères citation comme <,> et & restant dans l'entrée après strip_tags (). Cela les empêche d'être mal interprétés comme code HTML et permet de s'assurer qu'ils sont correctement affichés dans n'importe quelle page.

Après avoir présenté ces trois fonctions, il y a quelques points à rajouter au sujet de leur utilisation. De toute évidence, nl2br () et htmlspecialchars () sont adaptés pour le formatage de sortie, appelée sur les données juste avant qu'elle soit affichées, permettant aux données de la base de données ou des fichiers stockés afin de conserver le formatage normal tel que avec les nouvelles lignes et les caractères tels que &. Ces fonctions sont conçues principalement pour s'assurer que la sortie des données dans une page HTML est présentée avec soin, même après strip_tags () fonctionnant sur n'importe quelle sorte d’entrée.

strip_tags (), d'autre part, doit être exécuté immédiatement après la saisie des données, avant que tout autre traitement se produit. Le code ci-dessous est une fonction pour nettoyer l'entrée d'utilisateur de toutes les balises PHP ou HTML, et fonctionne à la fois méthodes GET et POST de la requête.

fonction _INPUT ($ nom)
{
if ($ _SERVER ['REQUEST_METHOD'] == 'GET')
strip_tags de retour ($ _GET [$ name]);
if ($ _SERVER ['REQUEST_METHOD'] == 'POST')
strip_tags de retour ($ _POST [$ name]);
}

Cette fonction pourrait facilement être élargie pour inclure les cookies dans la recherche d'un nom de variable. Je l'ai appelé _INPUT parce qu'il inclut directement les tableaux $ _ qui stockent l'entrée utilisateur. Notez également que lorsque vous utilisez cette fonction, il n'a y pas d'importance si la page a été demandée par un GET ou une méthode POST, le code peut utiliser _INPUT () et attendre la bonne valeur indépendamment de la méthode d’envoi. Pour utiliser cette fonction, considérons les deux lignes de code, qui toutes deux ont le même effet, mais la seconde protège le PHP et les balises HTML, augmentant ainsi la sécurité du script.

$ Nom = $ _GET ['nom');
$ Nom = _INPUT ('name');

Si les données doivent être saisies dans une base de données, le traitement est nécessaire pour éviter l'injection SQL, qui sera discuté plus tard.

Exécution de code contenant des entrées de l'utilisateur
Autre préoccupation lorsqu'il s'agit de données de l'utilisateur est la possibilité d’exécuter dans le code PHP ou sur le système. PHP fournit la fonction eval() qui permet à du code PHP arbitraire dans une chaîne doit être évalué (RUN). Il y a aussi la fonction system (), passthru () et fonctions exec () et l'opérateur accent grave, qui permettent une chaîne à être exécuté comme une commande du shell du système d'exploitation.

Lorsque cela est possible, l'utilisation de toutes ces fonctions devrait être évitée, surtout lorsque l'entrée d'utilisateur est entré directement dans une commande ou dans du code. Un exemple d'une situation où cela peut conduire à l'attaque est la commande suivante, qui affiche les résultats de la commande sur la page web.

echo 'Votre journal d'utilisation: <br />';
$ Username = $ _GET ['username'];
relais ("cat / logs / usage / $ username");

passthru () exécute une commande et affiche le résultat en sortie du script PHP, qui est inclus dans la dernière page que l'utilisateur voit. Ici, l'intention est évidente, un utilisateur peut passer leur nom d'utilisateur dans une requête GET comme usage.php? Username = nicolas et leur journal d'utilisation serait affiché dans la fenêtre du navigateur.

Mais que faire si l'utilisateur passe l'URL suivante?

? usage.php username = andrew; cat% 20/etc/passwd

Ici, la valeur de nom d'utilisateur contient désormais un point-virgule, qui est une commande shell terminateur, et une nouvelle commande par la suite. Le 20% est un espace de code URL, et est converti en un espace automatiquement par PHP. Maintenant, la commande qui est lu par passthru () est :

cat / logs / usage / andrew; cat / etc / passwd

Clairement ce genre d'abus de commande ne peut être autorisé.
Un attaquant pourrait utiliser cette vulnérabilité pour lire, supprimer ou modifier n'importe quel fichier du serveur web. Heureusement, une fois de plus, PHP intervient pour fournir une solution, sous la forme de la fonction escapeshellarg (). escapeshellarg () qui détruit tous les caractères qui pourraient causer un argument ou une commande résiliante. À titre d'exemple, les apostrophes ou des guillemets dans la chaîne sont remplacés par \ "ou \", et des points-virgules sont remplacées par \;.
Ces remplacements, et tous ceux effectuées par escapeshellarg (), assurez-vous que le code tel que celui présenté ci-dessous est bien sûr pour être lancé.

$ Username = escapeshellarg ($ _GET ['username']);
relais ("cat / logs / usage / $ username");

Maintenant, si l'attaquant tente de lire le fichier de mot de passe en utilisant la chaîne de requête ci-dessus, le shell va tenter d'accéder à un fichier appelé "/ logs / usage / André; cat / etc / passwd", et va échouer, car ce fichier est n’existe certainement pas.

Il est généralement considéré que eval () a appelé code contenant l'entrée d'utilisateur à être évitée à tout prix, il y a presque toujours une meilleure façon d'obtenir l'effet désiré. Toutefois, si cela doit être fait, assurez-vous que strip_tags a été appelé, et que les guillemets et les caractères d'échappement ont été déjà été rendus.

En combinant les techniques ci-dessus pour fournir un bon nettoyage de balises, évitant les caractères shell spéciaux, des entrées de validation d'expression basée sur HTML sont régulières, il est possible de construire des scripts Web sécurisés avec relativement peu de travail. En particulier, en utilisant une fonction telle que le _INPUT () présentée ci-dessus dans la version sécurisée d'acquisition d'entrée est s pas plus difficile que la version PHP fournit qui, elle, n’est pas sécurisée.

 

Comment faire pour vérifier les vulnérabilités PHP ?
La meilleure façon de vérifier si votre site Web et applications sont vulnérables aux attaques PHP est d’utiliser un scanner de vulnérabilités Web. Un scanner de vulnérabilités Web explore l'ensemble de votre site Web et vérifie automatiquement les vulnérabilités aux attaques PHP. Il vous indiquera quels scripts sont vulnérables afin que vous puissiez corriger la vulnérabilité facilement. Outre les failles de sécurité PHP, un scanner d'applications Web vérifiera également pour l'injection SQL, Cross site scripting et autres vulnérabilités susceptibles de se trouver sur votre site web.