Se nettoyer avec PHP

La sécurité des données est importante et souvent sous-estimée par les concepteurs, les développeurs et les clients. Depuis PHP 5.2.0, la désinfection et la validation des données ont été considérablement simplifiées grâce à l'introduction du filtrage des données. Aujourd'hui, nous allons examiner de plus près ces filtres, comment les utiliser et créer quelques fonctions personnalisées..

Détails du tutoriel

  • Programme: PHP
  • Version: 5.2.0+
  • Difficulté: Débutant
  • Temps d'exécution estimé: 20 minutes

introduction

J'ai toujours pensé qu'il était facile d'écrire du code en PHP et encore plus facile d'écrire du mauvais code en PHP. La prolifération de PHP sur le Web a été grandement facilitée par son utilisation dans des progiciels populaires à code source ouvert tels que WordPress, Drupal et Magento, ainsi que par d’importantes applications Web comme Facebook; PHP étant utilisé dans de nombreuses instances variées (sites Web dynamiques, applications Web détaillées, plates-formes de blogging, systèmes de gestion de contenu et commerce électronique, n'étant qu'un sous-ensemble des nombreuses applications de PHP), les opportunités de sale les données et les systèmes non sécurisés sont nombreux. Ce tutoriel expliquera quelques méthodes de Se purifier avec PHP: désinfection et validation des données en se concentrant sur différentes formes de saisie de données et sur l'utilisation des filtres PHP et des fonctions personnalisées.

Pourquoi assainir et valider?

Dans ce tutoriel, nous nous concentrons vraiment sur les entrées de données que des utilisateurs ou des sources externes peuvent fournir. Cela signifie que nous ne contrôlons pas les données que nous recevons. Tout ce que nous pouvons faire, c'est contrôler ce qui est fait après l'avoir reçu. Il existe toutes sortes de menaces liées à la sécurité des données provenant d'entrées utilisateur et de données tierces..

Certains ONU-menaces courantes pour la sécurité des données:

  • XSS (Cross-Site Scripting): Forme d’injection de code dans laquelle un script est injecté sur un site Web à partir d’un site Web complètement différent. Il s'agit de loin de la vulnérabilité de sécurité la plus courante en ligne. Le Stalk Daily et le Mikeyy Twitter Worms de cette année, qui utilisaient des entrées mal désinfectées pour lancer le Javascript via une interface Web "infectée", sont deux exemples récents et très remarquables de cette technique..
  • Injection SQL: La deuxième faille de sécurité la plus courante en ligne, il s’agit d’une autre forme d’injection de code dans laquelle un script est utilisé pour participer à l’un des nombreux comportements d’exploitation, notamment la divulgation et / ou l’accès non autorisé à des données, la modification de données à l’intérieur. d'une base de données, ou simplement en injectant du code à restituer ou à exécuter au sein d'un site Web, cassant ou modifiant ainsi le site Web.
  • Falsification de requête intersite (CSRF / XSRF): Un exploit moins courant qui repose davantage sur des sources de données telles que les cookies de navigateur et de session que sur des entrées de données mal filtrées et validées, CSRF (prononcé "sea-surf") peut être utilisé pour exécuter des commandes sur un site Web sans l'autorisation de l'utilisateur. Une méthode CSRF populaire consiste à utiliser un URI ou une valeur src de données d'image mal formés pour exécuter un script au lieu d'afficher une image..
  • Données incorrectes: Pas vraiment une "faille de sécurité" en soi, Des données incorrectes peuvent causer des problèmes aux hôtes d'un propriétaire de site Web ou d'un administrateur de base de données. Souvent, des données incorrectes peuvent endommager des sites Web mal codés ou provoquer le blocage de systèmes automatisés. Un exemple de ceci est la possibilité de modifier des pages entières de profil MySpace en postant en utilisant toutes sortes de hackery HTML / CSS (Note: cela peut encore fonctionner, je n'ai pas utilisé MySpace depuis longtemps)..
Source de l'image: XKCD

Pour nos besoins, nous allons nous concentrer uniquement sur les méthodes côté serveur permettant d’améliorer la sécurité des données avec PHP. Voyons donc comment les termes "nettoyage" et "validation" sont définis par rapport à PHP. Selon le manuel PHP:

La validation est utilisée pour valider ou vérifier si les données répondent à certaines qualifications. Par exemple, passer FILTER_VALIDATE_EMAIL déterminera si les données sont une adresse électronique valide, mais ne modifiera pas les données elles-mêmes..

La désinfection nettoie les données et peut donc les altérer en supprimant les caractères indésirables. Par exemple, passer FILTER_SANITIZE_EMAIL supprimera les caractères inappropriés pour une adresse e-mail. Cela dit, cela ne valide pas les données.

Essentiellement, si votre site Web est la boîte de nuit dans laquelle tout le monde veut entrer, la validation vérifie la liste des invités et les identifiants à la porte, tandis que la désinfection agit comme le videur qui rejette tous les indésirables qui se cachent derrière. Dans cet esprit, jetons un coup d'œil à PHP Filters Extension.

Quels filtres ai-je??

Toutes les installations PHP ne sont pas créées égales. Alors que PHP 5.2.0 était l'introduction de filtres, toutes les installations n'ont pas le même ensemble de filtres dans leur extension de filtres. La plupart des installations auront tous les filtres que nous allons examiner, mais pour vous en apprendre un peu plus sur l’extension des filtres, nous allons savoir ce que vous avez sur votre serveur. Dans le téléchargement source, j'ai inclus un fichier appelé getfilters.php qu’une fois installé et exécuté sur votre serveur, il affichera tous vos filtres (les deux filtres de données disponibles via le filter_var filtres de fonction et de flux disponibles via stream_filter_append).

 écho "

Filtres de données

\ n\ n\ n "; echo"\ n "; echo"\ n"; foreach (filter_list () as $ id => $ filter) echo"\ n "; echo"
ID de filtreNom du filtre
filtre $".filter_id ($ filter)."
\ n ";

Tout d’abord, nous obtenons le tableau contenant la liste de tous les filtres disponibles avec liste de filtres, puis nous parcourons le tableau et renvoyons l'écho au nom du filtre, trouvons l'ID attribué au filtre et renvoyons également cet identifiant.

Comment utiliser un filtre?

Les filtres PHP pour la validation et la désinfection sont activés en transmettant au moins deux valeurs à la fonction PHP Filters Extension filter_var. Par exemple, utilisons le filtre de désinfection pour un nombre entier comme ceci:

 $ value = '123abc456def'; echo filter_var ($ value, FILTER_SANITIZE_NUMBER_INT);

Dans l'exemple, nous avons une variable $ valeur qui est passé par la fonction Filtres Extension filter_var en utilisant le FILTER_SANITIZE_NUMBER_INT filtre. Cela se traduit par la sortie suivante:

 123456

Le filtre de désinfection pour un nombre entier supprime tous les caractères non-entiers de la sortie et produit un entier propre. Dans le code source de téléchargement, vous pouvez essayer différentes entrées et il appliquera un certain nombre de filtres communs à votre valeur d'entrée. J'ai inclus un certain nombre d'exemples de chaînes que vous pouvez tester aussi.

Que font les différents filtres?

La liste ci-dessous n'est pas complète, mais elle contient la majorité des filtres fournis en standard avec les installations 5.2.0+. Les filtres personnalisés et ceux ajoutés à partir d'extensions personnalisées ne sont pas inclus ici.

FILTER_VALIDATE_BOOLEAN: Vérifie si les données transmises au filtre sont ou non une valeur booléenne de VRAI ou FAUX. Si la valeur est une valeur non booléenne, elle retournera FAUX. Le script ci-dessous renvoie "TRUE" pour les données d'exemple. $ valeur01 mais echo "FALSE" pour les données d'exemple $ valeur02:

 $ valeur01 = TRUE; if (filter_var ($ value01, FILTER_VALIDATE_BOOLEAN)) echo 'TRUE';  else echo 'FALSE';  écho '

'$ valeur02 = TRUE; if (filter_var ($ value02, FILTER_VALIDATE_BOOLEAN)) echo 'TRUE'; else echo 'FALSE';

FILTER_VALIDATE_EMAIL: Vérifie si les données transmises au filtre sont ou non une adresse de messagerie potentiellement valide. Il ne vérifie pas si l'adresse de messagerie existe réellement, mais simplement que le format de l'adresse de messagerie est valide. Le script ci-dessous renvoie "TRUE" pour les données d'exemple. $ valeur01 mais echo "FALSE" pour les données d'exemple $ valeur02 (car le second manque de la partie @ domain.tld requise de l'adresse de messagerie):

 $ value01 = '[email protected]'; if (filter_var ($ value01, FILTER_VALIDATE_EMAIL)) echo 'TRUE';  else echo 'FALSE';  écho '

'$ value02 =' nettuts '; if (filter_var ($ value02, FILTER_VALIDATE_EMAIL)) echo 'TRUE'; else echo 'FALSE';

FILTER_VALIDATE_FLOAT: Vérifie si les données transmises au filtre sont ou non une valeur float valide. Le script ci-dessous renvoie "TRUE" pour les données d'exemple. $ valeur01 mais echo "FALSE" pour les données d'exemple $ valeur02 (car les séparateurs de virgule ne sont pas autorisés dans les valeurs flottantes):

 $ valeur01 = '1.234'; if (filter_var ($ value01, FILTER_VALIDATE_FLOAT)) echo 'TRUE';  else echo 'FALSE';  écho '

'$ valeur02 =' 1 234 '; if (filter_var ($ value02, FILTER_VALIDATE_FLOAT)) echo 'TRUE'; else echo 'FALSE';

FILTER_VALIDATE_INT: Vérifie si les données transmises au filtre sont ou non une valeur entière valide. Le script ci-dessous renvoie "TRUE" pour les données d'exemple. $ valeur01 mais echo "FALSE" pour les données d'exemple $ valeur02 (car les fractions / nombres décimaux ne sont pas des nombres entiers):

 $ valeur01 = '123456'; if (filter_var ($ value01, FILTER_VALIDATE_INT)) echo 'TRUE';  else echo 'FALSE';  écho '

'$ value02 =' 123.456 '; if (filter_var ($ value02, FILTER_VALIDATE_INT)) echo 'TRUE'; else echo 'FALSE';

FILTER_VALIDATE_IP: Vérifie si les données transmises au filtre sont ou non une adresse IP potentiellement valide. Il ne vérifie pas si l'adresse IP résoudrait, mais s'il correspond à la structure de données requise pour les adresses IP. Le script ci-dessous renvoie "TRUE" pour les données d'exemple. $ valeur01 mais echo "FALSE" pour les données d'exemple $ valeur02:

 $ valeur01 = '192.168.0.1'; if (filter_var ($ value01, FILTER_VALIDATE_IP)) echo 'TRUE';  else echo 'FALSE';  écho '

'$ valeur02 =' 1.2.3.4.5.6.7.8.9 '; if (filter_var ($ value02, FILTER_VALIDATE_IP)) echo 'TRUE'; else echo 'FALSE';

FILTER_VALIDATE_URL: Vérifie si les données transmises au filtre sont ou non une URL potentiellement valide. Il ne vérifie pas si l'URL résoudrait, mais s'il correspond à la structure de données requise pour les URL. Le script ci-dessous renvoie "TRUE" pour les données d'exemple. $ valeur01 mais echo "FALSE" pour les données d'exemple $ valeur02:

 $ value01 = 'http://net.tutsplus.com'; if (filter_var ($ value01, FILTER_VALIDATE_URL)) echo 'TRUE';  else echo 'FALSE';  écho '

'$ value02 =' nettuts '; if (filter_var ($ value02, FILTER_VALIDATE_URL)) echo 'TRUE'; else echo 'FALSE';

FILTER_SANITIZE_STRING: Par défaut, ce filtre supprime les données d'une chaîne non valide ou non autorisée dans cette chaîne. Par exemple, cela supprimera toutes les balises HTML, comme '; echo filter_var ($ value, FILTER_SANITIZE_STRING);

Ce script supprime les balises et renvoie les éléments suivants:

 alerte ('TROUBLE HERE');

FILTER_SANITIZE_ENCODED: Beaucoup de programmeurs utilisent PHP urlencode () fonction pour gérer leur encodage d'URL. Ce filtre fait essentiellement la même chose. Par exemple, cela encodera tous les espaces et / ou les caractères spéciaux d'une chaîne d'entrée:

 $ valeur = ''; echo filter_var ($ value, FILTER_SANITIZE_ENCODED);

Ce script devrait coder la ponctuation, les espaces et les crochets, puis renvoyer ce qui suit:

 % 3Cscript% 3Ealert% 28% 27TROUBLE% 20HERE% 27% 29% 3B% 3C% 2Fscript% 3E

FILTER_SANITIZE_SPECIAL_CHARS: Par défaut, ce filtre encode en HTML des caractères spéciaux tels que des guillemets, des esperluettes et des crochets (en plus des caractères dont la valeur ASCII est inférieure à 32). Bien que la page de démonstration ne la rende pas très claire sans visualiser le code source (car les caractères spéciaux encodés en HTML seront interprétés et restitués), si vous examinez le code source, vous verrez que l'encodage est à l'œuvre:

 $ valeur = ''; echo filter_var ($ value, FILTER_SANITIZE_SPECIAL_CHARS);

Il convertit les caractères spéciaux en leur propre codage HTML:

 

FILTER_SANITIZE_EMAIL: Ce filtre fait exactement ce que l'on pourrait penser. Il supprime tous les caractères non valides dans les adresses de messagerie (comme les parenthèses, les crochets, les deux points, etc.). Par exemple, disons que vous avez accidentellement ajouté des parenthèses autour d'une lettre de votre adresse électronique (ne demandez pas comment, utilisez votre imagination):

 $ value = 't (e) [email protected]'; echo filter_var ($ value, FILTER_SANITIZE_EMAIL);

Il supprime ces parenthèses et vous récupérez votre belle adresse e-mail:

 [email protected]

C’est un excellent filtre à utiliser sur les formulaires de courrier en collaboration avec FILTER_VALIDATE_EMAIL pour réduire les erreurs des utilisateurs ou empêcher les attaques liées à XSS (certaines attaques XSS antérieures impliquant le renvoi direct des données originales dans un champ de courrier non nettoyé). au navigateur).

FILTER_SANITIZE_URL: Semblable au filtre de désinfection d'adresse de messagerie, ce filtre fait exactement ce que l'on pourrait penser. Il supprime tous les caractères non valides dans une URL (comme certains caractères UTF-8, etc.). Par exemple, disons que vous avez accidentellement ajouté un "®" dans l'URL de votre site Web (encore une fois, ne demandez pas comment, prétendez qu'un vélociraptor l'a fait):

 $ value = 'http: //net.tuts®plus.com'; echo filter_var ($ value, FILTER_SANITIZE_URL);

Il supprime les "®" indésirables et vous récupérez votre belle URL:

 http://net.tutsplus.com

FILTER_SANITIZE_NUMBER_INT: Ce filtre est similaire à FILTER_VALIDATE_INT, mais au lieu de simplement vérifier s’il s’agit d’un entier ou non, il supprime en réalité tout ce qui n’est pas un entier! Pratique, en effet, pour les spambots agaçants et les filous sous certaines formes:

 $ value01 = '123abc456def'; echo filter_var ($ value01, FILTER_SANITIZE_NUMBER_INT); écho '
'; $ valeur02 = '1.2.3.4.5.6.7.8.9'; echo filter_var ($ value02, FILTER_SANITIZE_NUMBER_INT);

Ces lettres et décimales idiotes sont projetées:

 123456 123456789

FILTER_SANITIZE_NUMBER_FLOAT: Ce filtre est similaire à FILTER_VALIDATE_INT, mais au lieu de simplement vérifier s’il s’agit d’un entier ou non, il supprime en réalité tout ce qui n’est pas un entier! Pratique, en effet, pour les spambots agaçants et les filous sous certaines formes:

 $ value01 = '123abc456def'; echo filter_var ($ value01, FILTER_SANITIZE_NUMBER_FLOAT); écho '
'; $ valeur02 = '1.2.3.4.5.6.7.8.9'; echo filter_var ($ value02, FILTER_SANITIZE_NUMBER_FLOAT);

Encore une fois, toutes ces lettres et décimales idiotes sont éjectées:

 123456 123456789

Mais si vous vouliez conserver une décimale comme dans l'exemple suivant:

 $ valeur = '1,23'; echo filter_var ($ value, FILTER_SANITIZE_NUMBER_FLOAT);

Il l'enlèverait toujours et retournerait:

 123

L'une des principales raisons pour lesquelles FILTER_SANITIZE_NUMBER_FLOAT et FILTER_SANITIZE_INT sont des filtres distincts est de permettre cela via un indicateur spécial "FILTER_FLAG_ALLOW_FRACTION" ajouté en tant que troisième valeur transmise à filter_var:

 $ valeur = '1,23'; echo filter_var ($ value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);

Il conserverait la décimale et renverrait:

 1,23

Options, drapeaux et contrôles de tableau, OH MY!

L'indicateur de ce dernier exemple n'est que l'une des nombreuses options, indicateurs et contrôles de tableau qui vous permettent d'avoir un contrôle plus granulaire sur les types de données à désinfecter, les définitions de délimiteurs, la manière dont les filtres traitent les filtres, etc. Pour en savoir plus sur ces indicateurs et d'autres fonctions liées aux filtres, consultez la section Extension de filtres du manuel PHP..

Autres méthodes de traitement des données avec PHP

Nous allons maintenant passer en revue quelques méthodes supplémentaires clés de désinfection des données avec PHP afin d’éviter que les "données altérées" ne causent des ravages sur vos systèmes. Celles-ci sont particulièrement utiles pour les applications fonctionnant encore avec PHP 4, car elles étaient toutes disponibles lors de sa publication..

htmlspecialchars: Cette fonction PHP convertit 5 caractères spéciaux en entités HTML correspondantes:

  • '&' (esperluette) devient '&'
  • "" "(guillemet double) devient" "" lorsque ENT_NOQUOTES n'est pas défini.
  • "(guillemet simple) devient '' 'uniquement lorsque ENT_QUOTES est défini.
  • '<' (less than) becomes '<'
  • '>' (supérieur à) devient '>'

Il est utilisé comme n'importe quelle autre fonction de chaîne PHP:

 echo htmlspecialchars ('$ string');

htmlentities: Comme htmlspecialchars, cette fonction PHP convertit les caractères en entités HTML correspondantes. La grande différence est que TOUT les caractères pouvant être convertis seront convertis. C’est une méthode utile pour masquer les adresses e-mail de certains robots collectant des adresses e-mail, car ils ne sont pas programmés pour lire les adresses HTML..

Il est utilisé comme n'importe quelle autre fonction de chaîne PHP:

 echo htmlentities ('$ string');

mysql_real_escape_string: Cette fonction MySQL aide à vous protéger contre les attaques par injection SQL. Il est considéré comme une pratique recommandée (voire obligatoire) de transmettre toutes les données envoyées à une requête MySQL via cette fonction. Il échappe à tous les caractères spéciaux qui pourraient poser problème et causerait de petites Bobby Tables à détruire la base de données d'un autre élève.

 $ query = 'SELECT * FROM table WHERE valeur = ". mysql_real_escape_string (" $ string'). ' LIMITE 1,1 '; $ runQuery = mysql_query ($ query);

Fonctions personnalisées

Pour beaucoup de gens, ces filtres et fonctions intégrés ne suffisent pas. La validation des données de certaines données telles que les numéros de téléphone, les codes postaux ou même les courriers électroniques nécessite souvent une validation et un masquage plus stricts. Pour ce faire, de nombreuses personnes créent des fonctions personnalisées à valider et leurs données sont réelles. Un exemple de cela peut être aussi simple que d'utiliser une requête MySQL pour rechercher les données dans une base de données de valeurs connues, comme ceci:

 function checkZipCode ($ value) $ zipcheck = 'SELECT COUNT (*) FROM' base '.' zipcodes 'WHERE value = "' filter_var (mysql_real_escape_string ($ value), FILTER_SANITIZE_NUMBER_INT)." '; $ count = mysql_query ($ zipcheck); if ($ count == 1) return TRUE;  else return FALSE; 

Vous pouvez créer d’autres fonctions personnalisées qui ne reposent pas sur des bases de données de valeurs connues et qui peuvent être créées en vérifiant les guillemets magiques, en supprimant les barres obliques et en s’échappant pour insertion dans une base de données:

 function cleanString ($ string) $ detagged = strip_tags ($ string); if (get_magic_quotes_gpc ()) $ stripped = stripslashes ($ detagged); $ escaped = mysql_real_escape_string ($ stripped);  else $ escaped = mysql_real_escape_string ($ detagged);  return $ escaped; 

Les possibilités sont infinies, en particulier si vous intégrez des expressions régulières, mais dans la plupart des cas, l'extension PHP Filters devrait faire l'affaire..

  • Suivez-nous sur Twitter ou abonnez-vous au fil RSS Nettuts + pour obtenir plus d'articles et de sujets sur le développement Web quotidiens.