Permissions POSIX    Enregistrer au format PDF

Linux a été conçu pour être un système multi-utilisateurs. En général, un seul utilisateur a un accès complet au système : le root. Cet aspect de Linux est très sécurisant. Par exemple, si un hypothétique virus affectait un utilisateur, il n’aurait pas la possibilité d’endommager le système, puisqu’il ne pourrait que travailler dans le dossier personnel de l’utilisateur, ce qui est rarement intéressant... Ainsi, ce compte administrateur devient la cible évidente des attaquants, car réussir à avoir le root signifie donc la contrôle complet du système.


par S3cur3D

En plus de ce compte root, il peut y avoir une multitude d’autres utilisateurs, d’autres groupes. Chaque groupe contient un ou plusieurs utilisateurs et chaque utilisateurs peut appartenir à plusieurs groupes. Chaque fichier est relié à un utilisateur et à un groupe. Il y a trois types de permission : r (read pour l’accès en lecture), w (write pour l’accès en écriture) et x (execute pour l’accès en éxécution). Chaque fichier donne des droits différents à l’utilisateur associé (appellé l’owner, ou propriétaire du fichier), au groupe associé et aux "autres" qui ne font pas parti du groupe et qui ne sont pas propriétaires du fichier. Ainsi, chaque fichier a 10 caractères associés : le premier indique si le fichier est un répertoire ou non (avec un d pour directory), les trois suivants pour l’ owner, les trois suivants pour le groupe et les trois derniers pour les autres.

Dans l’exemple suivant, le propriétaire du fichier (s’appellant ’fichier’), SeriousHack, a l’accès complet (lecture/écriture/éxécution) au fichier. Les membres du groupe Hacking ont quand à eux accès au fichier seulement en lecture et en éxécution (ils ne pourront pas le modifier). Enfin, les autres utilisateurs n’ont aucun accès au fichier :

    -rwxr-x--- 1 SeriousHack Hacking 18 2007-07-26 19:52 fichier

Seulement, il y a des fois où il est nécessaire d’autoriser des utilisateurs n’ayant pas les privilèges du root à utiliser des fonctions du systèmes réservées au root (l’ouverture d’une connexion vers l’extérieur, la modification d’un mot de passe, etc...). Une solution possible serait de donner les privilèges root à l’utilisateur. Du point de vue sécurité, celà paraît pour le moins dérangeant. A la place, il existe un système permettant de faire tourner un programme avec les privilèges de l’utilisateur possédant le fichier ou le programme, ainsi l’utilisateur peut éxécuter les fonctions dont il a besoin sans avoir un accès complet au système. Ce type de permission est appellé le "bit suid" (set user ID). Quand un programme possédant le bit suid est éxécuté, l’euid (effective user ID, ou ID réel de l’utilisateur) de l’ utilisateur est remplacé par l’uid du propriétaire du programme, puis le programme est éxécuté. Une fois que le programme est achevé, l’euid de l’utilisateur reprend sa valeur originale. Ce bit est dénoté par un s à la place du x dans la liste des permissions d’un fichier. De la même façon, il existe un sgid (set group ID) qui fonctionne de la même façon.

Par exemple, sous Linux, les utilisateurs souhaitant changer leur mot de passe doivent taper la commande passwd qui appelle le programme /usr/bin/passwd :

-rwsr-xr-x 1 root root 29036 2007-06-22 20:10 /usr/bin/passwd

Les programmes de ce type, appartenant au root et ayant le bit suid sont appellés les SRP (suid root programs).
Les esprits les plus vifs auront compris où nous voulons en venir : en changeant le flux d’éxécution d’un programme qui a le bit suid, on éxécute ce flux en tant que le propriétaire du programme. Par exemple, si l’attaquant décide de faire créer à un SRP un shell (terminal de commande sous linux), le shell ainsi créé sera donc celui du root et l’attaquant aura ainsi gagné l’accès complet au système alors qu’il n’était que simple utilisateur.

Le problème est désormais le suivant : comment l’attaquant peut-il modifier le flux d’éxécution d’un programme si celui-ci obéit à un ensemble de règles strictes, comme énoncé plus tôt ?
La réponse tient finalement dans l’abilité du programmeur à comprendre ce qui se passe derrière ses lignes de code : la plupart des programmes sont écrits dans des langages dits de haut niveau (comme C, delphi, perl, php, etc...). Ecrire un programme dans ce type de langage ne nécessite pas une compréhension en profondeur de ce qui est impliqué, comme l’allocation des variables en mémoire, les appels à la pile ou les pointeurs d’éxécution. Un hacker travaillant en bas niveau (langage assembleur ou shellcode) sera forcé d’être amené à assimiler ces notions et à les manipuler. Ainsi, un hacker aura une meilleure compréhension du flux d’éxécution que ne l’aura le programmeur de haut niveau. Au final, changer le flux d’éxécution n’est en aucun cas casser les règles d’éxécution, mais les connaître mieux et les utiliser d’une façon que personne n’aurait pu anticiper. Pour pouvoir développer ce type d’exploitations ou écrire des programmes les empêchant, il est tout d’abord nécessaire de comprendre des règles de plus bas niveau, comme l’utilisation de la mémoire.

Documentations publiées dans cette rubrique