Université de Caen Basse-Normandie Département d informatique, U.F.R. Sciences Licence pro. ATC, Webmestre, 2015 2016 Unité UE14 Approfondissement programmation objet Cours. Sécurité des scripts Bruno Zanuttini 1 Types d attaques Parmi les attaques qui peuvent être lancées sur Internet, on peut considérer que les plus faciles sont celles menées contre les clients. Viennent ensuite celles contre les serveurs, et enfin celles sur les communications. Contre les serveurs, on peut recenser les principaux types suivants : accès à des données confidentielles stockées sur le serveur, exécution de commandes, parmi lesquelles la destruction de fichiers, installation de chevaux de Troie (logiciels destinées à faciliter une attaque ultérieure), défiguration d un site Internet, déni de service (Denial of Services, DoS) et sa version distribuée (DDoS). De façon générale, parmi les moyens de protection on trouve notamment une bonne configuration du serveur, une minimisation des services, et l écriture de scripts et applications sécurisés. 2 Ne pas faire confiance aux données entrées par l internaute Un site Web dynamique utilise en général de nombreuses données fournies par les internautes, que ce soit via des formulaires, via des URL (méthode GET) ou encore via des cookies. La règle de base dans le traitement de telles données est de toujours les valider avant de les utiliser. Les données fournies par les internautes peuvent permettre les types d attaques suivants. Les injections système consistent à changer la signification d une commande système exécutée par le serveur en introduisant des caractères spéciaux dans les données. Elles peuvent résulter en la possibilité, pour l internaute, de faire exécuter une commande système quelconque par le serveur. Les injections SQL (par exemple) consistent de même à changer la signification d une requête à une base de données en jouant sur les caractères spéciaux. Une telle attaque 1
peut permettre de contourner une authentification, de voir des données confidentielles, ou encore de modifier la structure de la base de données. Le cross-site scripting (XSS) consiste par exemple à inclure, dans des données fournies au site Web, des balises HTML. Si le site affiche ces données plus tard, en particulier pour un autre visiteur (cross-site), les balises seront interprétées. Le site peut ainsi être défiguré, faire «planter» les navigateurs de ses visiteurs, etc. Les cross-site request forgeries (CSRF) consistent à faire appeler un script par une victime (un autre internaute), à son insu. Le script en question est alors appelé avec les droits, l adresse IP, etc. de la victime, avec de fait la possibilité de passer des barrières de sécurité. On fait ainsi exécuter une attaque par un internaute à son insu. Outre les instructions système et les requêtes aux bases de données, on doit se méfier des instructions de la famille des include(url), en particulier si l URL est construite à partir des données fournies par l internaute. Un autre exemple d attaque, générique, est l exploitation d un buffer overflow. Cette technique (difficile à mettre en oeuvre) consiste à imposer à une application d écrire plus de données qu elle ne le peut dans la zone de mémoire qui lui est réservée. Le résultat est que les données en trop risquent d être écrites dans la zone mémoire qui contrôle le déroulement même de l application. Il est alors possible, quoique difficile, de modifier ce déroulement. Concernant le langage PHP, il faut également se méfier du fait que les variables (globales) n ont pas besoin d être déclarées, et ne jamais se reposer sur leurs valeurs par défaut. En effet, ces variables peuvent dans certains cas être modifiées par un utilisateur du script, via la méthode GET par exemple. Notons que la configuration par défaut de PHP4+ empêche cette possibilité (option register_globals=off), mais que cette configuration peut avoir été modifiée. 3 Écriture d applications sécurisées Il s agit de façon générale de filtrer les données entrées par l utilisateur. Il est difficile d établir une manière générale de filtrer, mais les caractères spéciaux tels que ceux du shell et ceux servant à introduire des commentaires dans les différents langages ont rarement des raisons d être présents dans un champ rempli par un visiteur du site. Lorsque c est possible, il est encore mieux de ne garder que les caractères valides plutôt que d en retirer certains. En effet, il paraît par exemple raisonnable de ne garder que les chiffres dans un champ «date de naissance», ou encore de ne garder que les lettres dans un champ «nom». En PHP, plusieurs fonctions permettent de réaliser de tels filtrages. Citons les suivantes (toutes ces fonctions retournent une nouvelle chaîne de caractères). escapeshellarg(string) échappe les guillemets de string, et l entoure de guillemets de sorte qu avec une bonne probabilité, le résultat puisse être utilisé en toute sécurité comme argument d une commande shell. escapeshellcmd(string) échappe les caractères spéciaux du shell, prévenant ainsi les 2
attaques utilisant, par exemple, le tube ou le point-virgule. addslashes(string) est écrite pour les requêtes à des bases de données. Elle échappe les simples et doubles guillemets et l antislash. stripslashes(string) fait l inverse. trim(string,liste) supprime les caractères présents dans liste de string. htmlentities(string) remplace dans string tous les caractères qui peuvent l être par les entités HTML équivalentes. htmlspecialchars(string) a le même effet que htmlentities, mais seulement pour les caractères ayant une signification spéciale en HTML. strip_tags(string) retire toutes les balises HTML de string (sauf celles d une éventuelle liste spécifiée). D autre part, l option magic_quotes_gpc de PHP (dans sa configuration) réalise automatiquement le travail de addslashes pour les données obtenues par GET, POST et COOKIES, avant de les passer à un script. Concernant les injections SQL, on peut s en protéger en utilisant des requêtes préparées (avec des variables pour chaque champ provenant de l utilisateur et utilisé dans la construction de la requête). De telles requêtes sont définies indépendamment des valeurs des paramètres. Ceux-ci ne sont liés à la requête que dans un deuxième temps, la syntaxe (parsing) de la requête ne pouvant alors plus être modifiée. En PHP, PDO, par exemple, propose des requêtes préparées. Concernant les CSRF, il faut faire en sorte qu aucune action importante ne puisse être exécutée via un simple appel de script. Il est également préférable de privilégier la méthode POST à la méthode GET pour la récupération des paramètres, car alors la victime se rendra compte de l attaque (affichage du résultat du post). Enfin, on peut mettre en œuvre des techniques plus élaborées, consistant à vérifier que le script critique a bien été appelé depuis un formulaire émis par le serveur. On peut ainsi cacher un nombre aléatoire (différent à chaque fois et pour chaque utilisateur) dans ces formulaires et vérifier qu il a bien été renvoyé lors de l appel du script. Notons que le fait de ne permettre aucune action importante via un simple appel de script est un conseil à suivre, même indépendamment des attaques possibles : penser au rechargement d une page, par exemple, qui ferait exécuter deux fois l action importante sans que l utilisateur ne le souhaite. 4 Applications exécutées côté client Il peut être tentant d utiliser des langages tels que JavaScript pour valider les données entrées par un visiteur, ou encore de limiter les données possibles en les faisant choisir à l utilisateur dans une liste, via un formulaire. Mais il ne faut pas perdre de vue que l attaquant fait ce qu il veut sur sa machine. En particulier, il peut enregistrer la page Web, en supprimer la fonction JavaScript de validation ou ajouter des possibilités dans les listes, puis utiliser cette page modifiée pour appeler le script. Cette remarque vaut également pour les cookies, car il suffit à l internaute d en éditer le fichier sur sa machine pour en modifier les valeurs. 3
Plus généralement, il est vain de se reposer sur des applications exécutées côté client pour la sécurité. 5 Messages d erreur et d information Les messages d erreur, et plus généralement d information, qu affiche un script, peuvent être une précieuse source d informations pour un attaquant, qui peut de plus chercher à les provoquer en fournissant des données non valides. De façon générale, et même s il ne faut pas se reposer sur ce seul point, la non connaissance d un script augmente la difficulté d exploiter ses failles. Il faut donc éviter des messages d erreur montrant, par exemple, une instruction dont l exécution a échoué. À titre d exemple, il est préférable d afficher «authentification impossible» plutôt qu «identifiant inconnu» ou «mauvais mot de passe». En effet, dans le second cas l attaquant peut obtenir plus rapidement la connaissance d un identifiant valide : au lieu d essayer de deviner un couple, il n a plus qu à chercher un identifiant valide, puis le mot de passe correspondant. Notons cependant qu un identifiant valide est souvent facile à deviner («root», «user», ou encore les adresses électroniques). 6 Dénis de services Les attaques de type déni de service visent à rendre un site Web ou un serveur inopérant, à y interdire l accès à une personne normalement autorisée, etc. Il est en général très difficile de se protéger contre ces attaques, parce qu elles exploitent la fonction même du serveur, c est-à-dire fournir des services. Un exemple consiste à envoyer de très nombreuses requêtes au serveur afin de le saturer. Une autre attaque consiste à essayer de faire révoquer le certificat d un site Web sécurisé via SSL. Les clients n y accepteront alors plus la connection, ou tout du moins demanderont confirmation à l utilisateur. Notons que de tels dénis de services peuvent être très graves pour les finances d une entreprise de vente par Internet, pour la réputation d une société d informatique, etc. Une autre attaque de type déni de service consiste à essayer d empêcher à une personne autorisée l accès à un site Internet ou à un compte. On peut par exemple exploiter des scripts qui bloquent un compte après trois mauvais mots de passe. 7 Options PHP Il est possible de surcharger, au niveau utilisateur, la valeur de certaines options de configuration de PHP. On peut utiliser pour cela la fonction ini_set dans un script PHP. La syntaxe 4
est ini_set( option, valeur ). La fonction phpinfo permet d obtenir des informations sur la configuration courante. Bien entendu, seules certaines options, choisies en général par l administrateur, sont modifiables. Si PHP est installé en tant que module d Apache, on peut également changer la valeur de ces options via les fichiers.htaccess. On utilise pour cela les directives php_value option valeur ou php_flag option on/off. 5