dimanche 15 juillet 2012

Résolution du challenge "Bandit"


A force de ne plus poster ici, j'en avais presque oublié l'existence de ce blog. Aussi, pour me ratrapper un peu je vous propose ma solution au challenge "Bandit" hébergé par overthewire que j'ai découvert récemment. Comme vous pourrez le voir, il n'est pas bien complexe, et sa résolution prend tout au plus 1h-1h30, pour une vingtaine de niveaux. Le niveau de difficulté n'est pas spécialement croissant, en fait c'est assez variable; certains des derniers niveaux peuvent être résolus en une dizaine de secondes, quand certains des premiers niveaux peuvent demander quelques minutes. Il ne s'agit pas d'un challenge de sécurité à proprement parler, mais plutôt de skillz en ligne de commande UNIX (néanmoins, ça peut représenter une bonne initiation aux challenges de sécurité type CTF).


Vu que mon but n'est pas de balourder bêtement une série de commandes UNIX permettant la résolution (autant refiler directement le mot de passe du dernier niveau), j'essaie d'expliquer au maximum mon raisonnement à chaque étape.

Niveau 0 :
Comme indiqué dans l'intitulé du niveau, le but est de se logguer sur la machine bandit.labs.overthewire.org avec le login bandit0 et le même mot de passe.

meik@athena:~$ ssh bandit0@bandit.labs.overthewire.org
[...]
bandit0@bandit.labs.overthewire.org's password: 
Welcome to Ubuntu 11.04 (GNU/Linux 2.6.38-8-virtual x86_64)
[...]
bandit0@melissa:~$

Voilà, à vaincre sans péril, on triomphe sans gloire. En même temps il s'agit du premier niveau d'un challenge assez simple.

Niveau 1 :
On reste connecté en tant que bandit0 (étape précédente). L'intitulé du niveau nous dit que le mot de passe permettant d'accéder au niveau suivant se situe dans un fichier nommé "readme" dans le répertoire home. Ce mot de passe nous permettra de nous authentifier en tant que "bandit1".

On vérifie qu'on est bien dans notre répertoire home avec la commande pwd :

bandit0@melissa:~$ pwd
/home/bandit0

On vérifie la présence du fichier "readme" avec la commande "ls" :

bandit0@melissa:~$ ls -l
total 4
-rw-r----- 1 bandit1 bandit0 33 2012-05-10 23:51 readme

On affiche son contenu avec la commande "cat" :

bandit0@melissa:~$ cat readme 
boJ9jbbUNNfktd78OOpsqOltutMc3MY1


Niveau 2 :
On utilise le mot de passe obtenu précédemment afin de se logguer en tant que bandit1 :

meik@athena:~$ ssh bandit1@bandit.labs.overthewire.org
[...]
bandit1@bandit.labs.overthewire.org's password: 
[...]
bandit1@melissa:~$

On nous dit que dans notre dossier home il y a un fichier dont le nom est "-", et ce fichier contient notre mot de passe. Facile, allons y avec "cat" :

bandit1@melissa:~$ cat -
[rien]

Il ne se passe rien. En fait, la commande "cat", lorsqu'elle a en paramètre "-", elle n'affiche pas un fichier nommé comme ça. Ce paramètre signale à la commande "cat" qu'elle va devoir récupérer des données sur stdin (le flux d'entrées standard, grosso modo le clavier). Alors comment faire pour afficher un fichier nommé "-" si cat ne le permet pas ? Eh bien on va feinter et faire croire à "cat" que le fichier a un nom sensiblement plus long, et surtout, qu'il ne commence pas par un "-" en utilisant le préfixe "./" qui signale que le fichier se trouve dans le dossier courant (chemin relatif):

bandit1@melissa:~$ cat ./-
CV1DtqXWVFXTvM2F0k09SHz0YwRINYA9

Ca marche. Notez que ça fonctionne également en passant le chemin complet du fichier :

bandit1@melissa:~$ cat /home/bandit1/-
CV1DtqXWVFXTvM2F0k09SHz0YwRINYA9


Niveau 3 :
Tout comme dans le niveau précédent, le mot de passe se situe dans un fichier présent dans le dossier home. Comme à l'instant, un "cat" sur le nom de fichier seul ne suffit pas. En effet, cat va croire qu'on veut afficher le contenu des fichiers "spaces", "in", "this" et "filename", sauf qu'aucun de ces fichiers là n'existe. On va devoir feinter d'une de ces deux manières :

- échapper les caractères d'espacement :
$ cat spaces\ in\ this\ filename
Cela permet "d'ignorer" les espaces en tant que délimiteurs de paramètres.
- passer tous ces mots en un seul paramètre à l'aide des "" :
$ cat "spaces in this filename"

Notez que dans les deux cas, vous pouvez juste taper
$ cat spaces

Et le shell va compléter automatiquement le nom de fichier (dans ce cas là, il utilise la première méthode).

On obtient notre mot de passe pour le niveau suivant :
UmHadQclWmgdLOKQ3YNgjWxGoRMb5luK



Niveau 4 :
Ici le mot de passe se situe dans un fichier caché du dossier "inhere". D'après la page de manuel de la commande "ls", on va utiliser le paramètre "a" pour lister les fichiers cachés (fichiers dont le nom commence par un point '.') :

Allons dans le dossier "inhere" à l'aide de la commande "cd" (change directory) et affichons le contenu de ce dossier à l'aide de la commande "ls" et des paramètres qui vont bien :

bandit3@melissa:~$ cd inhere
bandit3@melissa:~/inhere$ ls -al
total 12
drwxr-xr-x 2 root    root    4096 2012-05-10 23:51 .
drwxr-xr-x 3 root    root    4096 2012-05-10 23:51 ..
-rw-r----- 1 bandit4 bandit3   33 2012-05-10 23:51 .hidden

Il y a effectivement un fichier caché dont le nom est .hidden. Affichons le comme tout fichier normal :
bandit3@melissa:~/inhere$ cat .hidden 
pIwrPrtPN36QITSp3EQaw936yaFoFgAB


Niveau 5 :
Cette fois, dans le dossier "inhere" on a plusieurs fichiers. On nous dit dans l'énoncé que notre mot de passe se situe dans le seul fichier lisible humainement du dossier. Voyons ça :

bandit4@melissa:~/inhere$ ls -l
total 40
-rw-r----- 1 bandit5 bandit4 33 2012-05-10 23:51 -file00
-rw-r----- 1 bandit5 bandit4 33 2012-05-10 23:51 -file01
-rw-r----- 1 bandit5 bandit4 33 2012-05-10 23:51 -file02
-rw-r----- 1 bandit5 bandit4 33 2012-05-10 23:51 -file03
-rw-r----- 1 bandit5 bandit4 33 2012-05-10 23:51 -file04
-rw-r----- 1 bandit5 bandit4 33 2012-05-10 23:51 -file05
-rw-r----- 1 bandit5 bandit4 33 2012-05-10 23:51 -file06
-rw-r----- 1 bandit5 bandit4 33 2012-05-10 23:51 -file07
-rw-r----- 1 bandit5 bandit4 33 2012-05-10 23:51 -file08
-rw-r----- 1 bandit5 bandit4 33 2012-05-10 23:51 -file09
bandit4@melissa:~/inhere$ cat ./-file00 
[données que je ne peux même pas copier en mode plaintext]

Bon ok. pas vraiment concluant. On pourrait afficher tous ces fichiers, on finirait par tomber sur le bon (-file07). Mais ce n'est pas la solution la plus élégante. L'énoncé nous conseille d'utiliser la commande "file". Oui, mais que fait cette commande ? Eh bien d'après la page de manuel (man file), elle nous indique le type d'un fichier. On va aller plus loin automatisant la recherche de différences entre fichiers via un mini "script" :

bandit4@melissa:~/inhere$ for i in ./*; do file $i; done
./-file00: data
./-file01: data
./-file02: data
./-file03: data
./-file04: data
./-file05: data
./-file06: data
./-file07: ASCII text
./-file08: data
./-file09: data

Cette commande consiste en une boucle (for) qui va lancer la commande "file" sur chaque fichier (un fichier différent à chaque itération) correspondant à un pattern donné (./*). On voit ici que "-file07" est un fichier d'un type différent des autres. Affichons le :

bandit4@melissa:~/inhere$ cat ./-file07 
koReBOKuIDDepwhWk7jZC0RTdopnAYKh


Niveau 6 :
Cette fois, nous devons trouver un fichier dont nous ne savons pas grand chose:

- il se situe dans le dossier "inhere"
- il est lisible humainement (heureusement)
- il fait 1033 octets
- il n'est pas exécutable

Allons dans le dossier "inhere" :

bandit5@melissa:~$ cd inhere/
bandit5@melissa:~/inhere$ ls
maybehere00  maybehere04  maybehere08  maybehere12  maybehere16
maybehere01  maybehere05  maybehere09  maybehere13  maybehere17
maybehere02  maybehere06  maybehere10  maybehere14  maybehere18
maybehere03  maybehere07  maybehere11  maybehere15  maybehere19

Bon ok, la méthode bourrinage va être un peu trop longue. On va utiliser la commande "find". En lisant la page de manuel (man find), on apprend qu'on peut spécifier la taille du fichier à l'aide de la commande "-size" suivie de la taille et de l'unité, dans notre cas la commande sera :

bandit5@melissa:~/inhere$ find ./ -size 1033c
./maybehere07/.file2

Affichons le contenu de ce fichier :
bandit5@melissa:~/inhere$ cat ./maybehere07/.file2
DXjZPULLxYr17uwoI01bNLQbtFemEgo7[...]


Niveau 7 :
Cette fois, on ne nous dit pas où est situe le fichier. On sait juste qu'il est quelque part sur le serveur et qu'il a ces propriétés :

- il appartient à l'utilisateur "bandit7"
- il fait partie du groupe "bandit6"
- il fait 33 octets

Comme on est bien élevés, on a lu la page de manuel de find, et ça nous donne la commande suivante :

bandit6@melissa:~$ find / -user bandit7 -group bandit6 -size 33c 2>/dev/null
/var/lib/dpkg/info/bandit7.password

Notez le petit "2>/dev/null" qui nous permet de rediriger le contenu du file descriptor 2 (stderr) vers /dev/null (autrement dit, en langage humain, ça nous permet de ne pas afficher les messages d'erreurs renvoyés par "find" lors de la recherche et dûs à des fichiers un peu spéciaux pas accessibles).

Affichons le mot de passe :
bandit6@melissa:~$ cat /var/lib/dpkg/info/bandit7.password
HKBPTKQnIay4Fw76bEy8PVxKEDQRKTzs


Niveau 8 :
Cette fois, nous avons un fichier "data.txt" qui contient notre mot de passe. On nous indique qu'il se situe à côté du mot "millionth". Un "ls" nous indique que ce fichier fait tout de même 4Mo, donc le parcourir à la main ne sera pas évident. On va donc voir si on ne peut pas faciliter cette recherche. La commande "head" nous permet d'afficher les premières lignes du fichier :

bandit7@melissa:~$ head data.txt 
toothpaste's   8Qu0FK3BZmkIj8JNJBNqTfZCaYlkyhi7
russet's   6f1kAhSjlmKIrPPCe7na5PdscB9bzqWk
lithography   EbBu8X0J12sYVH3ZmhNyf98vPzmN1duC
fisherman   PK7F2mPR0ZWurRuM7uM4Ax9odVmBVeOI
vaporizers   qKYU1t8tZANX4gacarW8PEFAvbgfpQOl
sequenced   EjcO8zOwsMGQUsZdNjaE0gFNa4CGT7S9
Benzedrine's   NXb0DMO27PlJRJkR3m3A3Ie7Bb88YLN1
Procrustes   8vhCvrtmViwoggcW4SWTky6axLiooaQB
earthwards   vrzDbocWB3MehcDSes14sHQ56JzWfMCQ

On voit qu'il y a un "mot" ainsi qu'une chaine de caractères ressemblant à ce qui pourrait être notre mot de passe sur chaque ligne. Alors on a là encore plusieurs possibilités :

- la triche en utilisant vi/emacs/autre et sa fonction de recherche
/millionth (dans vi)
- la méthode attendue :
bandit7@melissa:~$ grep "millionth" data.txt 
millionth   cvX2JJa4CFALtqS87jk27qwqGhBM9plV


Niveau 9 :
Dans ce niveau, nous avons un fichier contenant plein de chaines pouvant potentiellement être notre mot de passe. On nous donne une indication, c'est la seule ligne dont le contenu est unique qui nous intéresse. Bon, le problème c'est que toutes ces lignes se ressemblent un peu. On nous donne en "hint" la commande "uniq". En regardant la page de manuel (man uniq) on apprend que cette commande ne marche bien que lorsque les lignes se suivent. On va donc également trier le contenu du fichier à l'aide de la commande "sort, et rediriger la sortie du fichier trié vers "uniq" :

bandit8@melissa:~$ cat data.txt | sort | uniq -u
UsvVyFSfZZWbi6wgC7dAFyFuR6jQQUhR


Niveau 10 :
La commande "file" indique qu'on nous a mis en présence du fichier "data.txt" qui est un gros fichier de données binaires qui ne peuvent pas être affichées dans cat, head, etc. On va donc utiliser l'utilitaire "string" qui permet d'extraire les chaines de caractère d'un fichier :

bandit9@melissa:~$ strings data.txt
[...] (plein de chaines)

Pour simplifier, on nous indique que le fichier contient quelques lignes qui commencent par le caractère "=" et que notre mot de passe se situe sur l'une de ces lignes. On va filtrer à l'aide de la commande "grep" :

bandit9@melissa:~$ strings data.txt | grep '='
========== the
R=ev2,
NF=!^
M5Q=
========== password
TuI@=
========== iss
c   =$
w=RO
eD=p
jR=JlB
G========== truKLdjsbJ5g7yyJ2X2R0o3a5HQJFuLk
:=*1p
KA=%

Et hop, on repère immédiatement notre mot de passe (truKLdjsbJ5g7yyJ2X2R0o3a5HQJFuLk) et on passe à la suite...


Niveau 11 :
On nous indique ici que le mot de passe se situe dans le fichier data.txt qui a été encodé au format base64. On voit qu'il y a une commande "base64" sur le système et qu'elle permet d'encoder/décoder des données dans ce format. Redirigeons la sortie d'un "cat" vers cette commande :

bandit10@melissa:~$ cat data.txt | base64 -d
The password is IFukwKGsFW8MOq3IRFqrxE1hxTNEbUPR


Niveau 12 :
On nous a mis ici en présence d'un fichier "chiffré" à l'aide de l'algorithme rot13 (chaque lettre est décalée de 13 rangs) :

bandit11@melissa:~$ cat data.txt 
Gur cnffjbeq vf 5Gr8L4qetPEsPk8htqjhRK8XSP6x2RHh

On peut là encore résoudre ce problèmes de deux manières :
- trouver un décodeur rot13 sur google
- utiliser la commande "tr" qui permet d'effectuer des correspondances de caractères

On va donc indiquer à la commande tr que les caractères entre A et M devront être remplacés par des caractères allant de N à Z et inversement (idem pour les minuscules) :

bandit11@melissa:~$ cat data.txt | tr a-zA-Z n-za-mN-ZA-M
The password is 5Te8Y4drgCRfCx8ugdwuEX8KFC6k2EUu



Niveau 13 :
Cette fois ci, notre fichier "data.txt" a une apparence étrange :

0000000: 1f8b 0808 8538 ac4f 0203 6461 7461 322e  .....8.O..data2.
0000010: 6269 6e00 0141 02be fd42 5a68 3931 4159  bin..A...BZh91AY
0000020: 2653 5935 a61d 4000 0017 7fff fd73 cf7f  &SY5..@......s..
0000030: abf1 1f5f fffb ffff bdff 7ed0 ab5b acf9  ..._......~..[..
0000040: 7fff f7fd fe59 feff fdfb f7ff b001 3a68  .....Y........:h
0000050: d200 d00d 0000 3400 0d07 a400 0000 0340  ......4........@

Il s'agit de ce qu'on appelle un "dump hexa". Ca facilite la visualisation du contenu de données binaires. On nous indique qu'il s'agit du dump hexa d'un fichier compressé à de multiples reprises. Bien, mais que faire avec un dump hexa ? On pourrait s'amuser à le recréer à la main, mais en fait la commande "xxd" peut faire ça pour nous :

Créons d'abord un répertoire de travail dans /tmp/ :
bandit12@melissa:~$ mkdir /tmp/lolz
bandit12@melissa:~$ cd /tmp/lolz

Recréons maintenant le fichier original à partir du dump :
bandit12@melissa:/tmp/lolz$ xxd -r ~/data.txt > data.txt
bandit12@melissa:/tmp/lolz$ file data.txt 
data.txt: gzip compressed data, was "data2.bin", from Unix, last modified: Thu May 10 23:52:05 2012, max compression

Bon, il s'agit de données au format gzip. On peut renommer le fichier en data.txt.gz (gzip se plaint si le fichier n'a pas cette extension) ou alors utiliser zcat et rediriger la sortie vers un autre fichier :

bandit12@melissa:/tmp/lolz$ zcat data.txt > blah
bandit12@melissa:/tmp/lolz$ ls
blah  data.txt
bandit12@melissa:/tmp/lolz$ file blah 
blah: bzip2 compressed data, block size = 900k

Une archive bzip2, décompressons là :
bandit12@melissa:/tmp/lolz$ bzip2 -d blah
bzip2: Can't guess original name for blah -- using blah.out

Quel est le format du fichier qui vient de sortir ?
bandit12@melissa:/tmp/lolz$ file blah.out 
blah.out: gzip compressed data, was "data4.bin", from Unix, last modified: Thu May 10 23:52:05 2012, max compression

Encore du gzip...
bandit12@melissa:/tmp/lolz$ zcat blah.out > lol
bandit12@melissa:/tmp/lolz$ file lol
lol: POSIX tar archive (GNU)


du tar cette fois ci...
bandit12@melissa:/tmp/lolz$ tar -xvf lol 
data5.bin
bandit12@melissa:/tmp/lolz$ file data5.bin 
data5.bin: POSIX tar archive (GNU)
bandit12@melissa:/tmp/lolz$ tar -xvf data5.bin 
data6.bin
bandit12@melissa:/tmp/lolz$ file data6.bin 
data6.bin: bzip2 compressed data, block size = 900k
bandit12@melissa:/tmp/lolz$ bzip2 -d data6.bin
bzip2: Can't guess original name for data6.bin -- using data6.bin.out
bandit12@melissa:/tmp/lolz$ file data6.bin.out 
data6.bin.out: POSIX tar archive (GNU)
bandit12@melissa:/tmp/lolz$ tar -xvf data6.bin.out 
data8.bin
bandit12@melissa:/tmp/lolz$ file data8.bin 
data8.bin: gzip compressed data, was "data9.bin", from Unix, last modified: Thu May 10 23:52:05 2012, max compression
bandit12@melissa:/tmp/lolz$ zcat data8.bin > marre
bandit12@melissa:/tmp/lolz$ file marre 
marre: ASCII English text
bandit12@melissa:/tmp/lolz$ more marre 
The password is 8ZjyCRiBWFYkneahHwxCv3wb2a1ORpYL




Niveau 14 :
Pour ce niveau, pas de mot de passe à récupérer. On nous indique juste que le mot de passe pour le niveau suivant se situe dans /etc/bandit_pass/bandit14 et que seul l'utilisateur bandit14 peut le lire (ce qui n'est pas notre cas, vu qu'on est bandit13). On nous donne par contre la clé SSH privée de cet utilisateur. Si on lit attentivement la page de manuel openssh, on voit que le paramètre "-i" permet de spécifier une clé privée à utiliser. Voyons cela :

bandit13@melissa:~$ ssh -i sshkey.private bandit14@localhost
Could not create directory '/home/bandit13/.ssh'.
The authenticity of host 'localhost (127.0.0.1)' can't be established.
RSA key fingerprint is 9d:09:d9:46:84:df:f9:dd:cc:7c:dc:49:a0:95:b2:10.
Are you sure you want to continue connecting (yes/no)? yes
[...]
bandit14@melissa:~$ cat /etc/bandit_pass/bandit14 
4wcYUJFw0k0XLShlDzztnTBHiqxU3b3e

Parfait. Passons au niveau suivant. Vu qu'on a besoin de ce mot de passe, on le garde précieusement de côté...


Niveau 15 :
On nous demande d'envoyer le mot de passe qu'on vient d'obtenir sur le port 3000 de localhost. En regardant un peu les commandes suggérées dans les conseils, on retient les commandes "nc" et "telnet". Essayons "telnet" :

bandit14@melissa:~$ telnet localhost 30000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
4wcYUJFw0k0XLShlDzztnTBHiqxU3b3e
Correct!
BfMYroe26WYalil77FoDi9qh59eK5xNr


Niveau 16 :
Il s'agit de faire la même chose sur le port 30001, la différence est que le service tournant sur ce port s'attend à recevoir des données chiffrées. On retient la commande "openssl" avec son paramètre "s_client" :

bandit15@melissa:~$ openssl s_client -connect localhost:30001
CONNECTED(00000003)
[...]
BfMYroe26WYalil77FoDi9qh59eK5xNr
Correct!
cluFn7wTiGryunymYOu4RcffSxQluehd


read:errno=0




Niveau 17 :
D'après l'énoncé, c'est assez proche des deux niveaux précédents. La différence est qu'on ne nous dit pas sur quel port se trouve le service auquel envoyer notre mot de passe. On nous dit qu'on va en trouver plusieurs, mais que celui qui nous intéresse est en SSL et que c'est le seul qui ne nous renverra pas strictement la même chose que ce qu'on lui envoie (comme un écho).

On utilise la commande "nmap" pour lister les ports en écoute sur le serveur :

bandit16@melissa:~$ nmap localhost -p 31000-32000


Starting Nmap 5.21 ( http://nmap.org ) at 2012-07-09 17:40 CEST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00081s latency).
Not shown: 996 closed ports
PORT      STATE SERVICE
31046/tcp open  unknown
31518/tcp open  unknown
31691/tcp open  unknown
31790/tcp open  unknown
31960/tcp open  unknown


Nmap done: 1 IP address (1 host up) scanned in 0.10 seconds
bandit16@melissa:~$ 

Alors là j'ai pas trouvé de solution particulièrement élégante, si ce n'est tester chaque port à la main et voir si ce qu'il me renvoie est un bête écho ou pas, à l'aide de netcat (ou telnet). Lorsque ça n'est pas le cas, c'est que le port attend du SSL, et j'utilise "openssl s_client localhost:port" et je soumets le mot de passe ayant servi à m'authentifier.

On finit par tomber sur le port 31790 qui nous donne une clé privée RSA :

-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAvmOkuifmMg6HL2YPIOjon6iWfbp7c3jx34YkYWqUH57SUdyJ
imZzeyGC0gtZPGujUSxiJSWI/oTqexh+cAMTSMlOJf7+BrJObArnxd9Y7YT2bRPQ
Ja6Lzb558YW3FZl87ORiO+rW4LCDCNd2lUvLE/GL2GWyuKN0K5iCd5TbtJzEkQTu
DSt2mcNn4rhAL+JFr56o4T6z8WWAW18BR6yGrMq7Q/kALHYW3OekePQAzL0VUYbW
JGTi65CxbCnzc/w4+mqQyvmzpWtMAzJTzAzQxNbkR2MBGySxDLrjg0LWN6sK7wNX
x0YVztz/zbIkPjfkU1jHS+9EbVNj+D1XFOJuaQIDAQABAoIBABagpxpM1aoLWfvD
KHcj10nqcoBc4oE11aFYQwik7xfW+24pRNuDE6SFthOar69jp5RlLwD1NhPx3iBl
J9nOM8OJ0VToum43UOS8YxF8WwhXriYGnc1sskbwpXOUDc9uX4+UESzH22P29ovd
d8WErY0gPxun8pbJLmxkAtWNhpMvfe0050vk9TL5wqbu9AlbssgTcCXkMQnPw9nC
YNN6DDP2lbcBrvgT9YCNL6C+ZKufD52yOQ9qOkwFTEQpjtF4uNtJom+asvlpmS8A
vLY9r60wYSvmZhNqBUrj7lyCtXMIu1kkd4w7F77k+DjHoAXyxcUp1DGL51sOmama
+TOWWgECgYEA8JtPxP0GRJ+IQkX262jM3dEIkza8ky5moIwUqYdsx0NxHgRRhORT
8c8hAuRBb2G82so8vUHk/fur85OEfc9TncnCY2crpoqsghifKLxrLgtT+qDpfZnx
SatLdt8GfQ85yA7hnWWJ2MxF3NaeSDm75Lsm+tBbAiyc9P2jGRNtMSkCgYEAypHd
HCctNi/FwjulhttFx/rHYKhLidZDFYeiE/v45bN4yFm8x7R/b0iE7KaszX+Exdvt
SghaTdcG0Knyw1bpJVyusavPzpaJMjdJ6tcFhVAbAjm7enCIvGCSx+X3l5SiWg0A
R57hJglezIiVjv3aGwHwvlZvtszK6zV6oXFAu0ECgYAbjo46T4hyP5tJi93V5HDi
Ttiek7xRVxUl+iU7rWkGAXFpMLFteQEsRr7PJ/lemmEY5eTDAFMLy9FL2m9oQWCg
R8VdwSk8r9FGLS+9aKcV5PI/WEKlwgXinB3OhYimtiG2Cg5JCqIZFHxD6MjEGOiu
L8ktHMPvodBwNsSBULpG0QKBgBAplTfC1HOnWiMGOU3KPwYWt0O6CdTkmJOmL8Ni
blh9elyZ9FsGxsgtRBXRsqXuz7wtsQAgLHxbdLq/ZJQ7YfzOKU4ZxEnabvXnvWkU
YOdjHdSOoKvDQNWu6ucyLRAWFuISeXw9a/9p7ftpxm0TSgyvmfLF2MIAEwyzRqaM
77pBAoGAMmjmIJdjp+Ez8duyn3ieo36yrttF5NSsJLAbxFpdlc1gvtGCWW+9Cq0b
dxviW8+TFVEBl1O4f7HVm6EpTscdDxU+bCXWkfjuRb7Dy9GOtt9JPsX8MBTakzh3
vBgsyi/sN3RqRBcGU40fOoZyfAMT8s1m/uYv52O6IgeuZ/ujbjY=
-----END RSA PRIVATE KEY-----

On la copie quelque part dans /tmp/ et on utilise ssh pour se logguer en tant que bandit17 sur la machine, sans oublier de mettre les bons droits sur le fichier (openssh ignore la clé privée si elle est lisible par d'autres personnes que son propriétaire):

bandit16@melissa:/tmp/ololol$ chmod 600 ssh.key 
bandit16@melissa:/tmp/ololol$ ssh -i ssh.key localhost -l bandit17
Could not create directory '/home/bandit16/.ssh'.
The authenticity of host 'localhost (127.0.0.1)' can't be established.
RSA key fingerprint is 9d:09:d9:46:84:df:f9:dd:cc:7c:dc:49:a0:95:b2:10.
Are you sure you want to continue connecting (yes/no)? yes
Failed to add the host to the list of known hosts (/home/bandit16/.ssh/known_hosts).
[...]
Last login: Wed Jul 11 15:53:55 2012 from localhost
bandit17@melissa:~$


Niveau 18 :
On a deux fichiers dans le dossier :

bandit17@melissa:~$ ls -l
total 8
-rw-r----- 1 bandit18 bandit17 3300 2012-05-30 14:15 passwords.new
-rw-r----- 1 bandit18 bandit17 3300 2012-05-30 14:15 passwords.old

Le mot de passe est la seule ligne qui a changé entre les deux fichiers. Les hints de bas de page ne nous seront pas très utiles ici, on va régler ça avec la commande "diff" :

bandit17@melissa:~$ diff passwords.new passwords.old 
42c42
< kfBf3eYk5BPBRzwjqutbbfE887SVc5Yd
---
> bECYSoXjOeGseirUCztuCBDF3xXqE7By

Et notre gagnant est kfBf3eYk5BPBRzwjqutbbfE887SVc5Yd


Niveau 19 :
Ce niveau là aussi n'est pas bien compliqué. Lorsqu'on se loggue en tant que bandit18, on est (quasi) immédiatement déconnecté. L'énoncé du challenge nous explique qu'il y a une instruction dans le .bashrc qui nous déconnecte (en fait c'est juste un exit :))

Ici encore, rien de bien sorcier pour venir à bout de ce challenge, on va essayer de voir si on peut passer l'exécution d'une commande à ssh, si on a de la chance, son exécution se déroulera avant l'interprétation du .bashrc :

meik@athena:~$ ssh bandit18@bandit.labs.overthewire.org cat readme


This is the OverTheWire game server. More information on http://www.overthewire.org/wargames


Please note that wargame usernames are no longer level, but wargamename
e.g. vortex4, semtex2, krypton1, bandit13, ...


Note: at this moment, blacksun and drifter are not available.


bandit18@bandit.labs.overthewire.org's password: 
IueksS7Ubh8G3DCwVzrTd8rAVOwq3M5x
meik@athena:~$ 


Niveau 20 :
Encore un niveau pas bien complexe histoire de nous initier aux joies du setuid qui sont très utiles dans certains des quelques niveaux restants. On nous explique qu'il y a un programme dans notre dossier home qui nous permettra d'obtenir un accès au niveau suivant :

bandit19@melissa:~$ ls -l
total 8
-rwsr-x--- 1 bandit20 bandit19 7165 2012-05-30 14:16 bandit20-do

On voit en effet qu'il dispose du petit "flag" 's'. Dans la pratique qu'est ce que ça veut dire ? Ca veut dire que ce programme, lorsqu'il s'exécutera, disposera des privilèges de son propriétaire. Ici le propriétaire est "bandit20", donc lorsqu'on exécutera une commande, notre "euid" (effective UID) sera bandit20, alors que nous sommes loggué en tant que "bandit19".

Ici, le programme prend en paramètre une commande à exécuter :

bandit19@melissa:~$ ./bandit20-do 
Run a command as another user.
  Example: ./bandit20-do id

Essayons :

bandit19@melissa:~$ ./bandit20-do id
uid=11019(bandit19) gid=11019(bandit19) euid=11020(bandit20) groups=11020(bandit20),11019(bandit19)

Ca confirme ce qui a été dit plus haut donc. On a bien un euid de bandit20. Ce qui nous sera fort utile pour lire le fichier contenant le mot de passe du niveau suivant :

bandit19@melissa:~$ ls -l /etc/bandit_pass/bandit20 
-r-------- 1 bandit20 bandit20 33 2012-05-30 14:16 /etc/bandit_pass/bandit20

Ici, seul l'utilisateur "bandit20" a le droit de lecture ('r') sur ce fichier contenant le mot de passe. Si on utilise la commande "cat" avec notre petit programme suid, la commande "cat" sera exécutée avec les privilèges de l'utilisateur bandit20 et on pourra donc lire le fichier :

bandit19@melissa:~$ ./bandit20-do cat /etc/bandit_pass/bandit20 
GbKksEFF4yrVs6il55v6gwY5aVje5f0j


Niveau 20 :
Cette fois, on est à nouveau mis en présence d'un fichier setuid. Voyons comment il réagit lorsqu'on le lance sans paramètres :

bandit20@melissa:~$ ./suconnect
Usage: ./suconnect
This program will connect to the given port on localhost using TCP. If it receives the correct password from the other side, the next password is transmitted back.

Ok donc ce programme va se connecter sur un port TCP local qu'on lui passe en paramètre. S'il *reçoit* le bon mot de passe (on déduit que c'est notre mot de passe actuel), il nous envoie le mot de passe permettant d'accéder au niveau suivant (bandit21).

On va donc ouvrir un port sur la machine à l'aide de netcat :

bandit20@melissa:~$ nc -l 6666

Comme indiqué dans les notes du niveau, on va ouvrir un autre terminal, se connecter sur la machine via ssh et effectuer le reste de la manipulation depuis ce terminal, à savoir lancer le "suconnect" :

bandit20@melissa:~$ ./suconnect 6666

De retour dans notre premier terminal, on va envoyer le mot de passe

bandit20@melissa:~$ nc -l 6666
GbKksEFF4yrVs6il55v6gwY5aVje5f0j
gE269g2h3mw3pwgrj0Ha9Uoqen1c9DGr


Niveau 22 :
Pour ce niveau, on nous indique qu'une tache périodique cron se lance régulièrement. On regarde donc dans /etc/cron.d/ comme suggéré dans les indications, et on voit plusieurs fichiers, dont un cronjob_bandit22, dont on se doute que c'est celui qui nous intéresse vu le nom.

On jete un oeil dedans :

bandit21@melissa:~$ cat /etc/cron.d/cronjob_bandit22
* * * * * bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null

C'est donc une tache qui se lance toutes les minutes, qui lance le script /usr/bin/cronjob_bandit22.sh. Regardons le contenu de ce script :

bandit21@melissa:~$ cat /usr/bin/cronjob_bandit22.sh
#!/bin/bash
chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv

Ce script donne les droits 644 à un fichier dans /tmp et copie le contenu du fichier /etc/bandit_pass/bandit22 dedans (le mot de passe qui nous intéresse donc). Regardons le contenu de ce fichier :

bandit21@melissa:~$ cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
Yk7owGAcWjwMVRwrTesJEwB7WVOiILLI


Niveau 23 :
Ce niveau est également très simple. On nous suggère là encore de regarder dans /etc/cron.d, et on y trouve cronjob_bandit23 :

* * * * * bandit23 /usr/bin/cronjob_bandit23.sh &> /dev/null

Là encore, un script qui s'exécute toutes les minutes, en tant que l'utilisateur "bandit23" :

#!/bin/bash
myname=$(whoami)
mytarget=$(echo I am user $myname | md5sum | cut -d ' ' -f 1)
echo "Copying passwordfile /etc/bandit_pass/$myname to /tmp/$mytarget"

Ce script récupère le nom de l'utilisateur qui lance le script (dans la tache cron, ça sera bandit23), génère une chaine de caractères avec ce nom, calcule son hash md5 et récupère ce dernier, qui sera le nom d'un fichier dans /tmp/ qui contient le mot de passe qui nous intéresse. On va donc exécuter les mêmes commandes, en remplaçant "myname" par "bandit23", sinon le traitement s'appliquera à l'utilisateur "bandit22" et ça ne marchera pas :

bandit22@melissa:~$ echo I am user bandit23 | md5sum | cut -d ' ' -f 1
8ca319486bfbbc3663ea0fbe81326349
bandit22@melissa:~$ cat /tmp/8ca319486bfbbc3663ea0fbe81326349
jc1udXuA1tiHqjIsL8yaapX5XIAI6i0n


Niveau 24 :
La encore, on regarde dans /etc/cron.d, on trouve encore une tache cron, qui se lance en tant que bandit24 et qui exécute le script suivant :

bandit23@melissa:~$ cat /usr/bin/cronjob_bandit24.sh
#!/bin/bash
myname=$(whoami)
cd /var/spool/$myname
echo "Executing and deleting all scripts in /var/spool/$myname:"
for i in *;
do
    echo "Handling $i"
    ./$i
    rm -f $i
done

Ce script exécute tous les scripts présents dans le dossier /var/spool/bandit24 (vu que la tache cron s'exécute en tant que bandit24) et les supprime. On va donc créer un simple script shell qui copie le contenu de /etc/bandit_pass/bandit24 vers un fichier dans /tmp et donner les droits d'exécution à ce script :

bandit23@melissa:/var/spool/bandit24$ echo "cat /etc/bandit_pass/bandit24 > /tmp/abcde ; chmod 644 /tmp/kikoolol" > gna ; chmod 755 gna

On attend quelques secondes le temps que la tache cron s'exécute...

bandit23@melissa:/var/spool/bandit24$ cat /tmp/abcde
UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ

A ce stade là, on a fini le challenge : "At this moment, level 25 does not exist yet."