Ceci est un programme set-root-uid
$ls -l -rwsr-sr-x 1 root root 7406 2011-12-13 22:37 ./x*
int main(void) { printf( " UID GID \n" "Real %d Real %d \n" "Effective %d Effective %d \n", getuid (), getgid (), geteuid(), getegid() ); seteuid(600); printf( " UID GID \n" "Real %d Real %d \n" "Effective %d Effective %d \n", getuid (), getgid (), geteuid(), getegid() ); setuid(1000); printf( " UID GID \n" "Real %d Real %d \n" "Effective %d Effective %d \n", getuid (), getgid (), geteuid(), getegid() ); setuid(0); // HOW DOES THIS SUCCEED IN SETTING THE EUID BACK TO 0 printf( " UID GID \n" "Real %d Real %d \n" "Effective %d Effective %d \n", getuid (), getgid (), geteuid(), getegid() ); return 0 ; }
UID GID Real 1000 Real 1000 Effective 0 Effective 0 UID GID Real 1000 Real 1000 Effective 600 Effective 0 UID GID Real 1000 Real 1000 Effective 1000 Effective 1000 UID GID Real 1000 Real 1000 Effective 0 Effective 1000
La page de manuel indique que setuid changera l’ID réel, enregistré et effectif. Donc, après le setuid(1000)
appel setuid(1000)
, tous les trois passent à 1000
. Comment est-ce que setuid(0)
me laisse euid
à 0
?
Il y a deux cas,
- Vous souhaitez supprimer temporairement les privilèges root lors de l’exécution du programme setuid
- Vous voulez supprimer définitivement les privilèges root lors de l’exécution du programme setuid …
Cas 1:
Après l’exécution d’un programme setuid
1.seteuid(600); 2.setuid(1000); 3.setuid(0);
Dans ce cas, le privilège root peut être rétabli.
+----+------+------------+ | uid|euid |saved-uid | |----|------|------------| 1.|1000| 0 | 0 | 2.|1000| 600 | 0 | 3.|1000| 1000 | 0 | 4.|1000| 0 | 0 | | | | | +------------------------+
Cas 2:
Après l’exécution d’un programme setuid ,
1.setuid(1000); 2.setuid(0); +----+------+------------+ | uid|euid |saved-uid | |----|------|------------| 1.|1000|0 | 0 | 2.|1000|1000 | 1000 | | | | | +------------------------+
Dans ce cas, vous ne pouvez pas récupérer le privilège root. Ceci peut être vérifié par la commande suivante,
cat / proc / PROCID / task / PROCID / status | Moins
Uid: 1000 0 0 0 Gid: 1000 0 0 0
Cette commande affichera un Uid et un Gid et aura 4 champs (les trois premiers champs sont ceux qui nous intéressent). Quelque chose comme ci-dessus
Les trois champs représentent uid, euid et saved-user-id. Vous pouvez introduire une pause (une entrée de l’utilisateur) dans votre programme setuid et vérifier pour chaque étape le cat /proc/PROCID/task/PROCID/status | less
cat /proc/PROCID/task/PROCID/status | less
commande. Au cours de chaque étape, vous pouvez vérifier que l’ID utilisateur enregistré a été modifié comme indiqué.
Si vous êtes root et que vous modifiez l’ID utilisateur, les privilèges sont définitivement supprimés. Si l’ID utilisateur effectif n’est pas root, l’identifiant utilisateur enregistré n’est jamais touché et vous pouvez récupérer les privilèges root à tout moment.
DESCRIPTION setuid () définit l’ID utilisateur effectif du processus appelant. Si l’UID effectif de l’appelant est root, le véritable UID et l’ID utilisateur-set enregistré sont également définis.
Sous Linux, setuid () est implémenté comme la version POSIX avec la fonctionnalité _POSIX_SAVED_IDS. Cela permet à un programme set-user-ID (autre que root) de supprimer tous ses privilèges utilisateur, d’effectuer des tâches non privilégiées, puis de reconnecter l’ID utilisateur effectif d’origine de manière sécurisée.
Si l’utilisateur est root ou si le programme est set-user-ID-root, des précautions particulières doivent être sockets. La fonction setuid () vérifie l’ID utilisateur effectif de l’appelant et, s’il s’agit du superutilisateur, tous les ID utilisateur liés au processus sont définis sur uid. Après cela, il est impossible pour le programme de récupérer les privilèges root.
Ainsi, un programme set-user-ID-root souhaitant supprimer temporairement les privilèges root, assumer l’identité d’un utilisateur non privilégié, puis récupérer les privilèges root par la suite, ne peut pas utiliser setuid (). Vous pouvez accomplir cela avec seteuid (2).
(extrait du Manuel des programmeurs Linux, 2014-09-21, page setuid.2
)
O! Ces fonctions sont difficiles à utiliser correctement.
La page de manuel indique que setuid changera l’ID réel, enregistré et effectif. Donc, après le setuid d’appel (1000), tous les trois passent à 1000.
C’est le cas si et seulement si vous êtes euid 0. Au moment où vous appelez setuid(0)
, vous êtes cependant euid 1000 et enregistré uid 0 (vérifiez getresuid(2)
, par exemple). C’est pourquoi vous êtes en mesure de retrouver des privilèges.