Mis à jour : 23 Déc 2020
Cet article ne remplace pas de bonnes connaissances en PHP, mais peut vous donner de réels bons conseils pour booster votre sécurité.
Il n’y aura ici rien à copier/coller directement dans vos fichiers PHP. Cependant, nous croyons que ces conseils et bonnes pratiques vous apporteront des bénéfices à long terme, en comprenant et en appliquant les différents points en fonction de vos besoins et de votre contexte.
Cet article est le deuxième de notre série dédiée à la sécurité pour PHP. Le premier article “Protéger votre site : Bonnes pratiques de sécurité pour PHP #1” vous donne des indications pour la configuration de PHP, les mises à jour, l’organisation du code ainsi que le filtrage/échappement des données.
Nous allons à présent examiner les attaques les plus courantes, ainsi que les moyens de s’en défendre.
Injections SQL
Les injections SQL sont vraiment dévastatrices, mais peuvent être évitées en suivant quelques étapes simples.
Premièrement, assurez-vous que les privilèges utilisateurs dans la base de données sont limités (principe de moindre privilège). Par exemple, les actions réalisées par un utilisateur front-office dans la base de données devraient être exécutées par un utilisateur n’ayant des droits que sur les tables liées aux fonctionnalités front-end. S’il n’y a pas besoin de supprimer les données d’une table spécifique, alors ne donnez pas les droits de suppression à cet utilisateur sur cette table.
Ensuite, filtrez et nettoyez les données servant d’entrée aux instructions SQL (vous pouvez vous référer à la section filtrage et échappement des données de notre premier article).
Un moyen plus efficace pour se protéger des injections SQL (mais ne remplaçant pas le filtrage des données) est l’utilisation des “prepared statements” (requêtes paramétrées).
Pour voir comment implémenter les requêtes paramétrées : http://php.net/manual/fr/pdo.prepared-statements.php
Injections de commandes
Utiliser des exécutions de commandes via votre code PHP est très puissant, mais aussi très dangereux si les précautions nécessaires ne sont pas prises.
Il est donc recommandé de désactiver les fonctions dangereuses avec la directive disable_functions (dans le fichier php.ini).
De plus, une fois désactivées, ces fonctions ne pourront pas être utilisées par un pirate créant son propre code PHP via une potentielle autre faille.
disable_functions = show_source, exec, shell_exec, system, passthru, proc_open, popen, curl_exec, curl_multi_exec, parse_ini_file, show_source
Lors de l’utilisation de ces fonctions (si vous en avez absolument besoin), faites très attention aux paramètres passés en entrée. Vous devez vous assurer que les données sont strictement validées avec des listes blanches, et/ou filtrées.
Les commandes dans leur globalité ainsi que les arguments peuvent être échappés via les fonctions natives escapeshellcmd (http://php.net/manual/fr/function.escapeshellcmd.php) et escapeshellarg (http://php.net/manual/fr/function.escapeshellarg.php).
Vols de sessions
Les sessions reposent sur des identifiants de session.
Une attaque fréquente est la fixation de session, consistant à donner un identifiant de session à une victime avant que celle-ci ne s’identifie sur l’application, puis à utiliser ce même identifiant de session afin de récupérer la session de la victime.
Pour éviter de tels problèmes, quelques règles doivent être suivies :
- ne pas accepter d’identifiant de session en provenance des URL ou des requêtes POST (directive session.use_only_cookies dans php.ini).
- protéger les cookies de session avec les flags HttpOnly et Secure (paramètres session.cookie_secure et session.cookie_httponly dans php.ini)
- donner une meilleure entropie aux identifiants de session, en paramétrant : session.entropy_file = /dev/urandom dans php.ini, sur les systèmes Linux.
Un point important est également de régénérer les identifiants de sessions à un moment critique : quand les utilisateurs se connectent.
Vous pouvez déclencher un renouvellement d’identifiants de session en appelant la fonction session_regenerate_id (http://php.net/manual/fr/function.session-regenerate-id.php).
Des éléments complémentaires peuvent être implémentés pour ajouter de la sécurité à différents niveaux (défense en profondeur) :
- garder une trace des dernières activités de l’utilisateur dans sa session, afin de détecter des activités suspectes sur des fonctions critiques.
- conserver le “user agent” dans la session et la vérifier à des moments clés.
- vérifier l’adresse IP n’est pas recommandé, étant donné qu’elle peut changer dynamiquement, par exemple sur les réseaux mobiles.
XSS
Protéger votre site contre les attaques XSS est assez simple, vous devez appliquer le principe “filter on input, escape on output” (voir notre article précédent).
Mais n’oubliez pas d’appliquer ces vérifications sur tous les paramètres, y compris les paramètres cachés, les paramètres GET/POST, cookies et headers HTTP.
Une protection complémentaire peut être mise en place grâce aux HTTP headers. Celle-ci a été détaillée dans notre article “Sécurisez votre site web avec les headers HTTP”.
Modification des paramètres
De nombreuses attaques s’appuient sur le fait que les URL et les formulaires peuvent être manipulés.
Attendez-vous à l’inattendu, et validez les paramètres avec des filtres et des listes blanches.
Le troisième article de notre série sur les bonnes pratiques de sécurité pour PHP traite des risques liés aux cookies, uploads, CRSF ainsi que de la sécurité par l’obscurité.