Développement et sécurité


<< Cross-Site Tracing


   Le but de cette section est de présenter les bonnes pratiques, les habitudes que les développeurs doivent prendre lors de l'écriture d'applications Web en général. Bien sûr, ces pratiques ne sont pas exhaustives, mais leur compréhension (plutôt que leur instrumentalisation) permet aux développeurs d'avoir un esprit critique vis-à-vis de la sécurité du code d'une application Web et d'effectuer eux-même les corrections puis d'intégrer de manière automatique ces "best practices".

Types des données
Le message essentiel de cette section est le vieux sermon All user input is evil until proven otherwise (Toute entrée utilisateur est malveillante tant que le contraire n'a pas été prouvé). En effet, il faut avoir cette habitude de canaliser de manière précise les données entrées et leur utilisation, vérifier qu'elles sont bien conformes à nos attentes et, si besoin, les nettoyer pour enlever toute possibilité de modification du comportement de notre application, qu'il soit minime ou important.

En premier lieu, les entrées doivent donc être cernées et vérifiées. Ainsi, si l'utilisateur doit entrer une date, vérifier qu'il s'agit bien d'une date (et valide de surcroît), si l'utilisation doit fournir un nombre à virgule flottante, vérifier que l'entrée se compose bien de chiffres avec un point ou une virgule, etc. Ceci revient donc à vérifier le typage des variables, types bien définis dans certains langages (comme C/C++ ou Java) mais bien moins dans la plupart des langages de scripts comme Python, Perl ou PHP. En effet, ceux-ci, bien que supportant le typage, peuvent travailler avec des types à utilisation générale (mixed en PHP par exemple), qui apporte un facilité de programmation indéniable.
Avant les préoccupations de sécurité, ces vérifications sont nécessaires au bon fonctionnement de l'application, afin d'être sûr des variables fournies et des traitements effectués. Il peut bien sûr arriver que les utilisateurs, par incompréhension, fautes de frappes ou autres, fournissent une valeur inadéquate, il va de soit qu'il est alors plus esthétique que l'application réponde "Veuillez entrer un nombre compris entre 1 et 100" plutôt que le rapport d'une erreur MySQL par exemple. Ceci dit, ces vérifications sont de nos jours souvent faites mais, comme vous l'avez sûrement compris en suivant les sections sur l'exploitation Web, doivent être étendues à toutes les variables avec lesquels l'utilisateur peut entrer en contact (variables GET, POST ou cookie en premier lieu, mais données extraites des bases de données également puisque les utilisateurs peuvent souvent y placer des valeurs, qui peuvent être déjà typées mais le sont rarement). Ces vérifications permettent dès lors de supprimer certaines attaques, comme les injections SQL sur les nombres ou certaines attaques de déni de service.

Enumération des valeurs Le typage ne fait pas tout. En effet, comme nous l'avons vu avec les failles includes, des entrées pouvant paraître légitime peuvent détourner le fonctionnement de l'application d'une manière que le développeur n'avait pas prévu. Dans le cas particulier des includes et dans bien d'autres, il est souvent possible de prédire les valeurs acceptables. Ainsi, sur une page d'accueil dynamique, il est possible de vérifier que les url incluses sont dans l'espace de valeurs "test.php", "b.php", etc. et effectuer l'inclusion si les pages sont en effet valide. D'autres sites plus dynamiques stockant leurs pages en base de données pourront vérifier que la page incluse correspond bien à un enregistrement. L'énumération des inclusions et affichage dynamiques permet également de supprimer les risques de directory traversal.

Assainissement des données
Ces pratiques ne nous permettent toujours pas de nous protéger. Comme exemple, il est possible de citer les injections SQL les plus basiques, avec les chaînes de caractères. En effet, il n'y a pas toujours de raison de considérer que le caractère ' ne peut pas faire partie d'un texte. Il faut donc considérer les autres applications amenées à utiliser la variable et se demander comment modifier ce texte de façon à ce que chacun y trouve son compte (texte non-modifié et sémantique de l'application conservée). L'assainissement demande des connaissances plus spécifiques aux applications. Dans le cas d'une requête SQL interprétée par un serveur, nous savons que les caractères ' et " mais aussi /* ou le carcatère null sont spéciaux. Il existe deux techniques communes d'assainissement : l'échappement et la traduction.
Le but de l'échappement est simple : placer un caractère spécial avant les autres caractères spéciaux afin de signaler à l'application "Attention, le prochain caractère n'est pas un caractère spécial, ne le traite pas en tant que tel". De cette manière, des fonctions comme real_escape_string() de MySQL ou addslashes() de PHP placent un antislash ou un guillemet avant les caractères spéciaux. Attention cependant aux particularités de certains jeux de caractères qui peuvent fausser l'ajout de ces caractères spéciaux. D'une manière générale, utiliser un jeu de caractères universel comme Unicode pour toutes les applications est recommandé.
La traduction est utilisée lorsque les occurences spéciales à remplacer sont potentiellement en nombre important. C'est ce qui est notamment utilisé afin de contrer les XSS. Ainsi, il est possible de remplacer un < par un &lt; ou un " par un &quot;. Lorsque le navigateur rencontre ce genre de caractères dans du code HTML, il les remplace automatiquement. Au final, lorsqu'un site Web doit afficher sur une page des données non-sûres (IP venant des headers HTTP, login ou autres données de la base de données), il doit prendre soin de les transformer, par exemple en PHP avec des fonctions comme htmlentities ou htmlspecialchars et d'utiliser les options de ces fonctions permettant un remplacement complet de tous les caractères spéciaux. En effet, les XSS sont bien plus génériques que l'on peut croire, une fonction comme striptags qui supprime les données entre balises (in fine pour supprimer les <script>...</script>, les tags img, etc.) ne protègera pas contre tous les types de XSS. Il est par exemple également important de modifier les simples et doubles guillemets.
L'assainissement des données est sans nul doute la sécurisation la plus dure à apporter, car elle implique une bonne connaissance des mécanismes sousjacents (comme le fonction de ces fonctions d'asinissement selon les différents jeux de caractères) et des vulnérabilités/exploitations possibles dans leur totalité. Bien que ce soit parfois nécessaire, il est souvent possible de typer au préalable les variables et éviter ainsi tous problèmes ultérieurs.

Protéger l'utilisateur
Nous n'avons pas souhaité détailler les attaques de type CSRF (Cross Site Request Forgery), car elles n'ont finalement pas vraiment de spécificité et sont assez aisées à comprendre. Elles relèvent plutôt de l'ingénieurie sociale ou du phishing, dans le sens où le but ultime est de faire cliquer l'utilisateur sur un lien qui enclenchera des actions non-souhaitées sur un autre site. En prenant l'exemple de site hautement populaires, comme Facebook ou iGoogle, on peut considérer comme non-négligeable la probabilité qu'un utilisateur soit identifié sur l'un de ces sites. Il est donc possible de créer des liens malveillants afin par exemple de modifier le mot de passe du compte, action qui sera exécutée si l'utilisateur clique sur le lien et est identifié sur l'un de ces sites. Afin de protéger les utilisateurs de ce genre de menaces, il est possible et facile de demander toujours une confirmation à l'utilisateur, par exemple en rentrant son mot de passe actuelle avant toute modification importante sur son profil. C'est ce qui est souvent fait de manière basique. De façon plus évoluée, les plus grands sites ont mis en place des systèmes de One-Time Tokens, des jetons qui sont créés de manière aléatoires à chaque affichage de page et injectés dans les liens que l'utilisateur peut visiter pour vérifier la cohérence de la navigation (au lieu de cliquer sur ?action=changepass, ce sera ?action=changepass&token=123423).
Bien sûr, tous les sites n'ont pas ce genre de problèmes à régler, mais lorsque des communautés même réduites apparaissent et peuvent communiquer (via forum, salons IRC ou autres), il est facile d'exposer les autres membres à ce type d'exploitation.

Modes de debug et indépendance de la plateforme
Enfin, nous terminons cet article sur le développement Web par certaines recommandation générales sur la mise en production de sites et d'applications Web. En premier lieu, une application publique n'est pas une application en développement. Il n'y a donc pas de raisons que les fichiers de recouvrement des divers éditeurs soient présents (les fichiers ~, .bak et autres). Ceci paraît bête, mais lorsque présents, ils permettent de lire la source ce qui peut souvent se réveler très dédommageable (mots de passes de bases de données par exemple). Mais surtout, une application en production utilise un interpréteur en production. J'entends par là qu'il faut prendre soin de désactiver les messages d'erreurs rendus par PHP, ASP ou n'importe quel interpréteur. Ainsi, une erreur SQL PHP, un fichier non trouvé en ASP, une exception dans une JSP, tous ces problèmes communs susceptibles d'arriver dans une application dynamique peuvent permettre, si les erreurs sont divulguées sur la page, il est possible de connaître l'arborescence du serveur (Path Disclosure) ou divulguer des parties de code contenant d'importantes informations pour l'attaquant (directives include, requête SQL, etc.). D'une manière générale, l'attaquant doit pouvoir en connaître le moins possible sur les mécanismes du site. Qui dit application en production dit serveur en production. Ainsi, il est impératifs de désactiver les méthodes de DEBUG que peut implémenter le serveur Web, notamment la méthode TRACE. Nous l'avons vu, cette méthode permet les attaques de type XST.
Le développeur doit également partir du principe qu'il ne connaît pas la configuration de la plateforme finale et qu'elle peut être différent de la plateforme de développement ou de celle de lancement (migration). Ainsi, la sécurité du développement ne doit jamais être lié à une quelconque configuration. Comme exemple primaire, il y a la variable d'état PHP magic_quotes_gpc. Lorsque celle-ci est activée, toutes les variables transitant par GET, POST ou Cookies seront échappées et les caractères NULL remplacés pr \0. Hormis le fait qu'elle utilise la fonction addslashes() peut avoir des comportements indésirables et remettre en cause la sûreté de l'échappement avec certains charset particuliers, il est évident que l'application doit avoir les mêmes fonctionnalités avec ou sans cette variable (par exemple, elle est désactivée sur les serveurs Free de pages personnelles). Ainsi, il faudrait tout de même échapper tous les GET, POST et Cookies d'une manière ressemblant à $var = mysql_real_escape_string(get_magic_quotes_gpc() ? stripslashes($var) : $var), qui vérifier si la variables est activée, si elle l'est supprime l'échappement, puis dans tous les cas elle applique la fonction real_escape_string de la librairie MySQL, plus sûre lors de requêtes vers un serveur MySQL.
Dans tous les cas, une bonne connaissance de la plateforme complète (serveur, interpréteur, langage) est nécessaire. Par exemple, il existe des vulnérablités spécifiques aux intéractions entre composants sur les plateformes SOA avec Java (comme Tomcat ou dérivés OSGi). La connaissance de la plateforme peut également permettre de configurer de plus près la sécurité de l'application. On peut citer l'option allow_include_url de PHP qui permet, lorsque mise à off d'empêcher toute inclusion distante de fichier, ce qui est souvent indésirable, ou le privilège FILES de MySQL, permettant de créer et de lire des fichiers sur le serveur, ce qui a également rarement un intérêt. Ainsi, le développement de ce genre d'applications demande ce genre de connaissances a priori.

Bien sûr, ces recommandations ne sont pas exhaustives. D'une manière générale, afin d'espérer développer du code sécurisé, il est nécessaire de consulter les best practices spécifiques au langage voire à la plateforme de développement et selon le contexte de l'application.


<< Cross-Site Tracing



23 Commentaires
Afficher tous


NAPSTER36 12/04/14 03:03
Merci ! très bon tutoriel :)

Anonyme 12/06/13 15:49
Merci, vous êtes les meilleurs...

Anonyme437 03/06/13 21:29
Une petite astuce à laquelle il faut aussi faire attention : il est possible d'insérer un tableau dans une variable get ou post. ex: index.php?page[]=1&page[]=test.

Anonyme 27/04/13 13:53
Merci beaucoup pour ton site, c'est une mine d'or




Commentaires désactivés.

Apprendre la base du hacking - Liens sécurité informatique/hacking - Contact

Copyright © Bases-Hacking 2007-2014. All rights reserved.