OverTheWire Bandit : mon parcours et mes notes #
Après avoir terminé le parcours Bandit proposé par OverTheWire, j’ai décidé de regrouper mes notes dans un article plus propre et plus structuré.
L’objectif de Bandit est d’apprendre progressivement à utiliser Linux, comprendre le fonctionnement du shell et découvrir quelques concepts de sécurité informatique à travers une série de défis de difficulté croissante.
Je ne détaille pas les mots de passe des niveaux afin de préserver l’intérêt pédagogique du parcours.
Niveau 0 #
Objectif #
Récupérer le mot de passe du niveau suivant.
Réflexion #
Le fichier contenant le mot de passe est directement présent dans le répertoire personnel. Une simple lecture du fichier suffit.
Solution #
cat readmeÀ retenir #
catpermet d’afficher le contenu d’un fichier texte.
Niveau 1 #
Objectif #
Lire un fichier dont le nom commence par un tiret (-).
Réflexion #
Sous Linux, un nom commençant par - est généralement interprété comme une option de commande. Il faut donc préciser explicitement qu’il s’agit d’un fichier.
Solution #
cat ./-À retenir #
-
Le préfixe
./permet de désigner un fichier situé dans le répertoire courant. -
Cela évite que le nom soit interprété comme une option.
Niveau 2 #
Objectif #
Lire un fichier contenant des espaces dans son nom.
Réflexion #
Les espaces ont une signification particulière dans le shell. Il faut soit les échapper, soit entourer le nom du fichier de guillemets.
Solution #
cat ./--spaces\ in\ this\ filename--Ou :
cat "./--spaces in this filename--"À retenir #
-
Un espace peut être échappé avec
\. -
L’autocomplétion avec la touche
Tabsimplifie souvent la saisie.
Niveau 3 #
Objectif #
Trouver un fichier caché.
Réflexion #
Les fichiers cachés sous Linux commencent par un point (.). La commande ls ne les affiche pas par défaut.
Solution #
ls -laUne fois le fichier identifié :
cat <nom_du_fichier>À retenir #
-
ls -aaffiche les fichiers cachés. -
ls -laajoute les permissions, propriétaires et tailles.
Niveau 4 #
Objectif #
Identifier un fichier lisible parmi plusieurs fichiers.
Réflexion #
Le dossier contient plusieurs fichiers dont un seul est exploitable. La commande file permet d’identifier leur nature.
Solution #
file ./*Une fois le bon fichier trouvé :
cat <fichier>À retenir #
-
filedétermine le type réel d’un fichier. -
Très utile lorsqu’une extension est absente ou trompeuse.
Niveau 5 #
Objectif #
Trouver un fichier répondant à des critères précis de taille.
Réflexion #
Ma première idée était de parcourir tous les répertoires avec ls puis de filtrer les résultats.
ls -la */* | awk '{print $5, $9}' | grep 1033Cette approche fonctionne partiellement mais ne prend pas en compte les fichiers cachés.
J’ai découvert que le caractère générique * ignore les fichiers commençant par un point.
Solution #
Activer temporairement l’inclusion des fichiers cachés :
shopt -s dotglobPuis relancer la recherche.
À retenir #
-
Les globes (
*) ignorent les fichiers cachés. -
dotglobmodifie ce comportement dans Bash.
Niveau 6 #
Objectif #
Trouver un fichier spécifique dans l’ensemble du système.
Réflexion #
Le fichier recherché possède plusieurs caractéristiques :
-
propriétaire spécifique ;
-
groupe spécifique ;
-
taille précise.
La commande find est parfaitement adaptée à ce type de recherche.
Solution #
find / -size 33c -user bandit7 -group bandit6 2>/dev/nullExplication #
2>/dev/nullredirige les erreurs vers la « poubelle » du système afin d’éviter d’être submergé par les messages de permission refusée.
À retenir #
-
findest l’outil de référence pour rechercher des fichiers. -
2>/dev/nullpermet de masquer les erreurs.
Niveau 7 #
Objectif #
Trouver une ligne particulière dans un gros fichier texte.
Réflexion #
Le mot de passe se trouve sur la même ligne qu’un mot-clé spécifique.
Solution #
cat data.txt | grep millionthVersion plus concise :
grep millionth data.txtÀ retenir #
-
greppermet de rechercher du texte dans un fichier. -
Éviter les pipes inutiles lorsque la commande accepte déjà un fichier en entrée.
Niveau 8 #
Objectif #
Trouver la seule ligne unique d’un fichier.
Réflexion #
Toutes les lignes sont dupliquées sauf une.
Solution #
sort data.txt | uniq -uÀ retenir #
-
uniqnécessite généralement un tri préalable. -
uniq -uaffiche uniquement les lignes uniques.
Niveau 9 #
Objectif #
Extraire du texte lisible depuis un fichier binaire.
Réflexion #
Le fichier contient principalement des données non textuelles.
Solution #
strings data.txt | grep "="À retenir #
-
stringsextrait les chaînes de caractères imprimables. -
Très utile lors de l’analyse de binaires.
Niveau 10 #
Objectif #
Décoder une chaîne encodée en Base64.
Solution #
base64 -d data.txtÀ retenir #
-
Base64 est un encodage, pas un chiffrement.
-
N’importe qui peut décoder une donnée encodée en Base64.
Niveau 11 #
Objectif #
Décoder un texte chiffré à l’aide de l’algorithme ROT13.
Analyse #
ROT13 est un chiffrement par substitution très simple. Chaque lettre est remplacée par celle située 13 positions plus loin dans l’alphabet. Comme l’alphabet contient 26 lettres, appliquer ROT13 une seconde fois permet de retrouver le texte original.
Sous Linux, la commande tr permet de réaliser facilement cette transformation.
Solution #
cat data.txt | tr 'A-Za-z' 'N-ZA-Mn-za-m'Ce qu’il faut retenir #
-
trpermet de transformer ou remplacer des caractères. -
ROT13 n’est pas un véritable mécanisme de sécurité mais un simple procédé d’obfuscation.
Niveau 12 #
Objectif #
Retrouver un mot de passe caché dans une succession d’archives compressées.
Analyse #
Ce niveau est probablement l’un des plus amusants du début du parcours. Le fichier fourni est un hexdump qu’il faut d’abord reconstruire avant de pouvoir l’exploiter.
Une fois le fichier restauré, on découvre une série d’archives imbriquées utilisant différents formats de compression.
Solution #
Reconstruction du fichier :
xxd -r data.txt > archivePuis identification et extraction répétée :
file archiveSuivie de :
gunzip
bunzip2
tar -xfselon le type de fichier rencontré.
Ce qu’il faut retenir #
-
xxd -rpermet de reconstruire un fichier à partir d’un dump hexadécimal. -
fileest indispensable lorsqu’on manipule des archives inconnues. -
Les formats de compression les plus courants sont
gzip,bzip2ettar.
Niveau 13 #
Objectif #
Se connecter à l’utilisateur suivant à l’aide d’une clé SSH privée.
Analyse #
Le niveau introduit l’authentification par clé SSH. Contrairement à une authentification classique par mot de passe, le serveur vérifie ici la possession d’une clé privée.
Une difficulté fréquente concerne les permissions du fichier contenant la clé.
Solution #
chmod 600 sshkey.privatePuis :
ssh -i sshkey.private bandit14@localhost -p 2220Ce qu’il faut retenir #
-
Une clé privée SSH ne doit être accessible qu’à son propriétaire.
-
SSH refuse généralement d’utiliser une clé dont les permissions sont trop permissives.
Niveau 14 #
Objectif #
Envoyer le mot de passe actuel à un service réseau local.
Analyse #
Le serveur écoute sur le port 30000 et attend simplement la réception du mot de passe du niveau précédent.
L’outil idéal pour ce type d’interaction est Netcat.
Solution #
nc localhost 30000Puis saisir le mot de passe demandé.
Ce qu’il faut retenir #
-
Netcat est souvent surnommé le “couteau suisse du réseau”.
-
Il permet d’établir rapidement des connexions TCP ou UDP.
Niveau 15 #
Objectif #
Réaliser la même opération que précédemment mais via SSL/TLS.
Analyse #
Cette fois, le service distant exige une connexion chiffrée.
Netcat ne gère pas TLS nativement, il faut donc utiliser OpenSSL.
Solution #
openssl s_client -connect localhost:30001Puis envoyer le mot de passe demandé.
Ce qu’il faut retenir #
-
TLS protège les communications réseau contre l’interception.
-
openssl s_clientest très pratique pour tester des services sécurisés.
Niveau 16 #
Objectif #
Identifier le bon service parmi plusieurs ports ouverts.
Analyse #
La première étape consiste à effectuer une reconnaissance réseau afin d’identifier les ports disponibles.
Un seul d’entre eux renvoie les informations nécessaires pour accéder au niveau suivant.
Solution #
nmap localhost -p 31000-32000Une fois le bon port identifié :
openssl s_client -connect localhost:31790Dans mon cas, j’ai rencontré un problème de buffering avec OpenSSL et j’ai finalement utilisé ncat.
Ce qu’il faut retenir #
-
L’énumération est souvent la première étape d’une phase d’exploitation.
-
nmapest l’un des outils les plus utilisés pour la reconnaissance réseau.
Niveau 17 #
Objectif #
Comparer deux fichiers afin d’identifier une différence.
Analyse #
Deux fichiers sont fournis : un ancien et un nouveau. Le mot de passe correspond à la ligne modifiée.
Solution #
diff passwords.old passwords.newCe qu’il faut retenir #
-
diffpermet de comparer rapidement deux fichiers. -
Cet outil est omniprésent dans les systèmes de gestion de versions.
Niveau 18 #
Objectif #
Contourner une configuration Bash modifiée.
Analyse #
Le fichier .bashrc a été altéré afin d’empêcher l’accès normal au shell.
Plutôt que de corriger la configuration, il est plus simple d’éviter Bash complètement.
Solution #
ssh bandit18@bandit.labs.overthewire.org -p 2220 "cat readme"Ou en lançant directement un autre shell.
Ce qu’il faut retenir #
-
Lorsqu’un environnement est cassé, il est souvent plus efficace de le contourner que de le réparer.
-
SSH permet d’exécuter directement une commande distante.
Niveau 19 #
Objectif #
Comprendre le fonctionnement d’un exécutable SUID.
Analyse #
Le programme fourni exécute une commande avec les privilèges d’un autre utilisateur.
Après quelques essais, on constate que l’exécutable accepte une commande en argument et l’exécute avec des permissions plus élevées.
Solution #
./bandit20-do cat /etc/bandit_pass/bandit20Ce qu’il faut retenir #
-
Les binaires SUID s’exécutent avec les privilèges de leur propriétaire.
-
Une mauvaise configuration SUID peut entraîner une élévation de privilèges.
Niveau 20 #
Objectif #
Mettre en place un serveur d’écoute afin de communiquer avec un programme client.
Analyse #
Le programme fourni doit contacter un serveur TCP local qui renvoie le mot de passe précédent.
Pour simplifier les manipulations, il est pratique d’utiliser plusieurs terminaux ou une session screen.
Solution #
Premier terminal :
nc -lvp 1234Second terminal :
./suconnect 1234Le programme contacte alors le serveur local, récupère le mot de passe et affiche celui du niveau suivant.
Ce qu’il faut retenir #
-
Netcat peut être utilisé aussi bien comme client que comme serveur.
-
Les outils de multiplexage comme
screenoutmuxdeviennent vite indispensables en environnement Linux.
Niveau 21 #
Objectif #
Comprendre le fonctionnement d’une tâche cron afin de récupérer le mot de passe du niveau suivant.
Analyse #
Dans le répertoire dédié aux tâches planifiées, on trouve un script exécuté automatiquement toutes les minutes.
L’idée est alors d’analyser ce script pour comprendre ce qu’il fait et où il stocke les informations qui nous intéressent.
En examinant son contenu, on découvre qu’il copie le mot de passe dans un fichier temporaire.
Solution #
Identifier la tâche :
cat /etc/cron.d/cronjob_bandit22Puis analyser le script appelé :
cat /usr/bin/cronjob_bandit22.shEnfin récupérer le contenu du fichier généré :
cat /tmp/<fichier_généré>Ce qu’il faut retenir #
- Les tâches cron sont fréquemment utilisées pour automatiser des opérations système.
- Une mauvaise gestion des fichiers temporaires peut exposer des informations sensibles.
Niveau 22 #
Objectif #
Déterminer où un script stocke le mot de passe.
Analyse #
Cette fois, le script ne stocke pas directement le mot de passe dans un emplacement évident.
Après analyse, on constate qu’il calcule un hash MD5 à partir de la chaîne :
I am user bandit23Ce hash est ensuite utilisé comme nom de fichier dans /tmp.
Solution #
Reproduire localement le calcul :
echo "I am user bandit23" | md5sumPuis consulter le fichier correspondant :
cat /tmp/<hash>Ce qu’il faut retenir #
- Lire le code est souvent plus efficace que de chercher à le contourner.
- Les fonctions de hachage servent fréquemment à générer des identifiants ou des noms de fichiers.
Niveau 23 #
Objectif #
Exécuter du code avec les privilèges d’un autre utilisateur.
Analyse #
Le script cron exécute tous les scripts présents dans un répertoire spécifique.
L’idée consiste donc à déposer notre propre script dans ce répertoire afin qu’il soit exécuté automatiquement avec les privilèges de l’utilisateur cible.
Solution #
Créer un script :
#!/bin/bash
cat /etc/bandit_pass/bandit24 > /tmp/passwordLe rendre exécutable :
chmod +x monscript.shPuis le déposer dans le répertoire surveillé.
Après quelques instants :
cat /tmp/passwordCe qu’il faut retenir #
- Les répertoires exécutés automatiquement représentent une surface d’attaque importante.
- Toujours contrôler précisément quels fichiers peuvent être exécutés par une tâche automatisée.
Niveau 24 #
Objectif #
Retrouver un mot de passe en réalisant une attaque par force brute.
Analyse #
Le service écoute sur un port TCP et attend deux informations :
- le mot de passe actuel ;
- un code PIN à quatre chiffres.
Le nombre de combinaisons possibles étant limité, une attaque exhaustive est envisageable.
Solution #
Générer toutes les combinaisons :
for i in {0000..9999}
do
echo "<motdepasse> $i"
donePuis envoyer le résultat au service :
nc localhost 30002Une fois le bon code trouvé, le serveur renvoie le mot de passe du niveau suivant.
Ce qu’il faut retenir #
- La taille de l’espace de recherche est essentielle lorsqu’on évalue la résistance d’un secret.
- Un code PIN à quatre chiffres est extrêmement faible.
Niveau 25 #
Objectif #
Contourner une configuration SSH inhabituelle.
Analyse #
Ce niveau est probablement l’un des plus déroutants du parcours.
Après inspection du compte cible, on découvre que le shell associé n’est pas un shell classique mais la commande more.
Lors de la connexion SSH, more est lancé automatiquement puis la session se ferme immédiatement.
L’astuce consiste à forcer l’entrée dans le mode interactif de more en réduisant la taille du terminal.
Depuis ce mode, il devient possible de lancer Vim.
Solution #
Une fois dans more :
vPuis dans Vim :
:set shell=/bin/bash
:shellOn obtient alors un shell avec les permissions de l’utilisateur.
Ce qu’il faut retenir #
- Les programmes interactifs peuvent parfois être utilisés pour sortir d’environnements restreints.
- Vim possède de nombreuses fonctionnalités permettant d’exécuter des commandes système.
Niveau 26 #
Objectif #
Exploiter un programme SUID afin d’accéder au mot de passe suivant.
Analyse #
Le répertoire personnel contient un exécutable appartenant à l’utilisateur suivant.
Après quelques essais, on constate qu’il exécute une commande avec des privilèges plus élevés.
Solution #
Lister le contenu du répertoire contenant les mots de passe :
./bandit27-do ls /etc/bandit_passPuis afficher le mot de passe :
./bandit27-do cat /etc/bandit_pass/bandit27Ce qu’il faut retenir #
- Les binaires SUID sont fréquemment impliqués dans les élévations de privilèges.
- Comprendre les permissions Linux est indispensable en sécurité offensive.
Niveau 27 #
Objectif #
Cloner un dépôt Git distant.
Analyse #
Le niveau introduit Git et les dépôts accessibles via SSH.
Une fois le dépôt cloné, le mot de passe apparaît directement dans son contenu.
Solution #
git clone ssh://bandit27-git@bandit.labs.overthewire.org:2220/home/bandit27-git/repoExplorer ensuite les fichiers du dépôt :
cat READMECe qu’il faut retenir #
- Git peut utiliser SSH comme protocole de transport.
- Un dépôt peut contenir des informations sensibles même lorsqu’elles semblent supprimées.
Niveau 28 #
Objectif #
Retrouver une information supprimée dans l’historique Git.
Analyse #
Le dépôt ne contient plus le mot de passe dans sa version actuelle.
En consultant l’historique des commits, on remarque un message indiquant la correction d’une fuite d’information.
Il est alors logique de consulter l’état précédent du dépôt.
Solution #
Afficher l’historique :
git logRestaurer ou afficher le commit précédent :
git checkout <commit>ou
git show <commit>Ce qu’il faut retenir #
- Supprimer un secret d’un dépôt ne suffit pas à le faire disparaître.
- L’historique Git conserve l’ensemble des versions précédentes.
Niveau 29 #
Objectif #
Explorer les différentes branches d’un dépôt Git.
Analyse #
Le contenu de la branche principale ne révèle rien d’intéressant.
Une énumération rapide montre cependant l’existence d’autres branches.
Solution #
Lister les branches :
git branch -aBasculer sur la branche de développement :
git checkout devLe mot de passe apparaît alors dans le fichier README.
Ce qu’il faut retenir #
- Les branches Git représentent des historiques indépendants.
- Une information supprimée d’une branche peut rester présente dans une autre.
Niveau 30 #
Objectif #
Explorer les tags Git.
Analyse #
Contrairement aux branches, les tags servent généralement à marquer une version particulière d’un projet.
Dans ce niveau, le mot de passe est directement stocké dans un tag.
Solution #
Lister les tags :
git tagAfficher leur contenu :
git show <tag>Ce qu’il faut retenir #
- Les tags permettent de marquer des points précis dans l’historique Git.
- Lors d’un audit, il ne faut jamais se limiter à la branche principale.
Niveau 31 #
Objectif #
Comprendre l’utilité du fichier gitignore
Analyse #
Un fichier gitignore spécifie des fichiers intentionnellement non suivis que git ignorera lors d’un push du dépôt.
Dans ce niveau tous les fichiers en .txt seront ignorés, il nous faut donc modifier le fichier .gitignore.
Solution #
Supprimer la ligne correspondant au .txt
vim .gitignoreCréer le fichier key.txt et effectuer le push
echo "May I come in?" > key.txt
git add key.txt
git commit -m key
git pushCe qu’il faut retenir #
Le fichier .gitignore nous permet d’ignorer tous les fichiers mentionnés à l’intérieur de celui-ci, lors d’un push.
Niveau 32 #
Objectif #
Découverte des variables.
Analyse #
Au sein de Linux il existe plusieurs types de variables : les variables locales (valides dans le Shell actuel), les variables Shell (définies par Shell) et les variables d’environnements (ensembles du système).
Elles sont définies comme suit :
NOM_VAR=valeur_varPour afficher la valeur d’une variable :
echo $VAR_NAMEOu toutes les variables :
printenvSolution #
Quand on se connecte au serveur on se rend compte que toutes les commandes qu’on essaye de passer se convertissent en majuscule. Autrement nos commandes sont convertis en variables. Elles ne fonctionnent donc pas. Pour récupérer un Shell normal on va appeler la variable $0 qui correspond au Shell.
$0
cat /etc/bandit\_pass/bandit33