OverTheWire: Bandit – 9 à 17

Cet article est le deuxième d’une série de quatre :

Niveau 9

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

Je dois retrouver le mot de passe dans data.txt. Cette fois-ci, on m’indique qu’il s’agit d’une des quelques chaînes de caractères lisibles et qu’il est précédé par plusieurs symboles =.

Je liste tout d’abord les chaînes lisibles avec strings :

bandit9@bandit:~$ strings data.txt | head
Z/,_
WW"&8
2Qk)
xWa_
x?Xn
//M$
;yzEt!
WpU~e
`Rn,I
VSXdK

strings sert à afficher les séries de caractères lisibles dans un fichier. Par défaut, il montre toutes celles composées de quatre caractères ou plus.

Les mots de passe des autres niveaux ont tous le même format, une chaîne de 33 caractères. C’est armé de cette information que je rajoute une longueur minimale de 33 caractères aux chaînes remontées par strings, ce qui réduit le nombre de résultats à une unique ligne :

bandit9@bandit:~$ strings -n33 data.txt
[[PASSWORD]]

Niveau 10

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

Ce niveau est assez direct : je dois lire le fichier data.txt, encodé en Base64.

Base64 est un encodage assez fréquemment utilisé pour convertir des fichiers binaires en une série de caractères lisibles : lettres capitales, bas-de-casse, chiffres, / et =. C’est notamment en Base64 que sont encodées les pièces jointes dans vos mails.

Pour décoder – et encoder – un fichier en Base64, j’utilise l’utilitaire base64.

bandit10@bandit:~$ base64 -d data.txt
The password is [[PASSWORD]]

Niveau 11

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

C’est encore un niveau ou je dois décoder data.txt, cette fois-ci en utilisant ROT13.

ROT13 est un chiffrage très simple à implémenter : chaque lettre est décalée de 13 caractères. Les A sont remplacés par des N, les B par des O, les C par des P, etc.

Il s’agit d’un cas spécifique n = 13 du chiffre de César, qui possède une propriété intéressante : rot13(rot13(text)) = text.

Pour décoder data.txt, je peux utiliser tr, un outil qui permet de remplacer certains caractères par d’autres. Je peux remplacer les caractères A à M par N à Z, N à Z par A à M, et de même pour le bas-de-casse.

bandit11@bandit:~$ tr 'A-Za-z' 'N-ZA-Mn-za-m' < data.txt
The password is [[PASSWORD]]

J’utilise < data.txt ici pour rediriger le contenu de data.txt vers l’entrée standard de tr. C’est une bonne pratique à prendre, qui évite une utilisation inutile de cat et sa forme cat data.txt | tr ….

Niveau 12

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

Le niveau 12 est un jeu du chat et de la souris. data.txt est un dump hexadécimal d’un fichier compressé plusieurs fois sous différents formats – gzip et bzip2 – et archivé avec Tar.

Tout d’abord, je me sers de xxd et de son option -r pour reformer le fichier original à partir du dump.

bandit12@bandit:~$ head data.txt
00000000: 1f8b 0808 0650 b45e 0203 6461 7461 322e  .....P.^..data2.
00000010: 6269 6e00 013d 02c2 fd42 5a68 3931 4159  bin..=...BZh91AY
00000020: 2653 598e 4f1c c800 001e 7fff fbf9 7fda  &SY.O...........
00000030: 9e7f 4f76 9fcf fe7d 3fff f67d abde 5e9f  ..Ov...}?..}..^.
00000040: f3fe 9fbf f6f1 feee bfdf a3ff b001 3b1b  ..............;.
00000050: 5481 a1a0 1ea0 1a34 d0d0 001a 68d3 4683  T......4....h.F.
00000060: 4680 0680 0034 1918 4c4d 190c 4000 0001  F....4..LM..@...
00000070: a000 c87a 81a3 464d a8d3 43c5 1068 0346  ...z..FM..C..h.F
00000080: 8343 40d0 3400 0340 66a6 8068 0cd4 f500  .C@.4..@f..h....
00000090: 69ea 6800 0f50 68f2 4d00 680d 06ca 0190  i.h..Ph.M.h.....

bandit12@bandit:~$ xxd -r data.txt | file -
/dev/stdin: gzip compressed data, was "data2.bin", last modified: Thu May  7 18:14:30 2020, max compression, from Unix

J’utilise une fois de plus file pour déterminer le type de chaque étape afin de simplifier l’exloration. Notez le trait d’union - à la place du nom de fichier, qui, comme vu au niveau 1, indique à file que je souhaite analyser l’entrée standard. J’utilise différents programmes jusqu’à obtenir un type text :

  • gunzip : décompresse les archives gzip ;
  • bzcat : invoque bzip avec les options --decompress et --stdout, pour décompresser les archives bzip2 ;
  • tar -xO : extrait les archives tar et envoie le résultat sur la sortie standard.
bandit12@bandit:~$ xxd -r data.txt | gunzip | file -
/dev/stdin: bzip2 compressed data, block size = 900k

…

bandit12@bandit:~$ xxd -r data.txt | … | bzcat | tar -xO | gunzip | file -
/dev/stdin: ASCII text

bandit12@bandit:~$ xxd -r data.txt | … | bzcat | tar -xO | gunzip
The password is [[PASSWORD]]

Niveau 13

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

Ici on me passe directement une clé SSH pour accéder au niveau 14. Je passe l’option -i à ssh pour l’utiliser :

bandit13@bandit:~$ ssh -i ./sshkey.private bandit14@localhost

bandit14@bandit:~$

Niveau 14

Je dois envoyer le mot de passe du niveau en cours – stocké dans /etc/bandit_pass/bandit14 à un service qui écoute sur le port 30000. J’utilise netcat pour cela :

bandit14@bandit:~$ nc localhost 30000 < /etc/bandit_pass/bandit14
Correct!
[[PASSWORD]]

netcat est un utilitaire extrêmement versatile que vous pouvez utiliser pour déboguer vos flux réseau. Ici je m’en sers uniquement pour rediriger le mot de passe sur un endpoint local.

Niveau 15

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

Je retrouve ici le même exercice que sur le niveau précédent, seulement cette fois-ci je dois utiliser SSL pour me connecter à localhost:30001.

Je remplace nc par openssl qui fournit un client SSL rudimentaire via la commande s_client :

bandit15@bandit:~$ openssl s_client -connect localhost:30001 -quiet < /etc/bandit_pass/bandit15
depth=0 CN = localhost
verify error:num=18:self signed certificate
verify return:1
depth=0 CN = localhost
verify return:1
Correct!
[[PASSWORD]]

Niveau 16

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

Même exercice que le niveau 15, mais le port n’est pas précisé. D’après l’énoncé, plusieurs services écoutent sur les ports 31000 à 32000, certains d’entre eux utilisent SSL et d’autres non. Un seul de ces services renverra le mot de passe de bandit17, et les autres ne renverront que le texte envoyé.

J’utilise nmap, un scanner de ports, pour détecter les ports ouverts et le service sous-jacent :

bandit16@bandit:~$ nmap -sV -p 31000-32000 localhost
…
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00030s latency).
Not shown: 996 closed ports
PORT      STATE SERVICE     VERSION
31046/tcp open  echo
31518/tcp open  ssl/echo
31691/tcp open  echo
31790/tcp open  ssl/unknown
31960/tcp open  echo
…
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 88.20 seconds

Cinq ports sont ouverts, et deux d’entre eux voient leurs communications chiffrées via SSL. Le service détecté derrière quatre de ces ports est appelé echo, il s’agit d’un leurre. Celui qui m’intéresse est le service « inconnu » derrière le port 31790.

Je reprends la commande de l’exercice précédent, en changeant le port utilisé ainsi que le mot de passe à donner :

bandit16@bandit:~$ openssl s_client -connect localhost:31790 -quiet < /etc/bandit_pass/bandit16
depth=0 CN = localhost
verify error:num=18:self signed certificate
verify return:1
depth=0 CN = localhost
verify return:1
Correct!
-----BEGIN RSA PRIVATE KEY-----
[[PASSWORD]]
-----END RSA PRIVATE KEY-----

En lieu de mot de passe, j’obtiens une clé privée. Je la sauvegarde dans un fichier temporaire et l’utilise pour me connecter en tant que bandit17 :

bandit16@bandit:~$ PRIVATE_KEY=$(mktemp)

bandit16@bandit:~$ openssl s_client \
  -connect localhost:31790 \
  -quiet < /etc/bandit_pass/bandit16 > $PRIVATE_KEY
depth=0 CN = localhost
verify error:num=18:self signed certificate
verify return:1
depth=0 CN = localhost
verify return:1

bandit16@bandit:~$ ssh -i $PRIVATE_KEY bandit17@localhost

bandit17@bandit:~$

mktemp est un programme fort pratique pour créer des fichiers ou dossiers temporaires, par défaut dans /tmp et avec un nom aléatoire et unique.

Niveau 17

Dans ce niveau j’ai deux fichiers, passwords.old et passwords.new de cent lignes chacun. Une de ces lignes diffère, car l’ancien mot de passe a été remplacé par celui du niveau 18.

J’utilise diff pour afficher les différences entre ces deux fichiers :

bandit17@bandit:~$ diff passwords.old passwords.new
42c42
< w0Yfolrc5bwjS4qw5mq1nnQi6mF03bii
---
> [[PASSWORD]]

… et ensuite ?

Vous retrouverez les solutions des niveaux 18 à 26 dans l’article suivant.