Supprimer les privilèges de processus


12

J'ai un processus qui est démarré par un damon exécuté en tant que root, maintenant je veux "rétrograder" les privilèges de ce processus à ceux de votre utilisateur moyen. Est-ce possible? Si oui comment?

PS: exécuter unix sur un mac

Réponses:


5

Le processus lui-même doit appeler setuid (2). Vous devriez également étudier son exécution dans chroot (8) si vous ne l'êtes pas déjà. Pour autant que je sache, root n'a aucun moyen de changer l'uid d'un autre processus.

Si la raison pour laquelle vous l'exécutez en tant que root est de lier des ports, je suggère de l'exécuter en tant qu'utilisateur normal sur un port supérieur et d'utiliser ipfw (8) sur OS X pour transférer le port 80/443 / etc vers le port supérieur:

http://support.crashplanpro.com/doku.php/recipe/forward_port_443_to_pro_server_on_mac_osx


J'ai mis setuid (uid) dans mon programme qui s'exécute en tant que root mais j'en ai besoin pour fonctionner en tant qu'utilisateur normal et rien ne se passe, c'est-à-dire qu'il continue de s'exécuter en tant que root
Samantha Catania

Vous devrez probablement en attraper les erreurs (vous obtenez peut-être un EINVAL pour l'uid). Son setuid improbable est cassé sur votre machine, vous pouvez le vérifier en voyant si apache fonctionne en tant que _www. Documents du programmeur: developer.apple.com/library/mac/#documentation/Darwin/Reference/…
polynôme

vous avez raison, cela donne une erreur de syntaxe de l'uid même si elle est correcte. est-ce le bon format setuid (500)?
Samantha Catania

a trouvé le problème: j'essayais d'exécuter la commande via system () mais je viens d'exécuter la commande ça marche & j'ai résolu mon problème; merci pour l'aide
Samantha Catania

Ce n'est pas un bon conseil: appeler setuid()seul ne suffit absolument pas.
Nicholas Wilson

13

sudo tcpdump -Z utilise initgroups (3), setgid (2) et setuid (2) pour supprimer les privilèges root de son propre processus.

# code taken from: 
# http://www.opensource.apple.com/source/tcpdump/tcpdump-32/tcpdump/tcpdump.c

/* Drop root privileges and chroot if necessary */
static void
droproot(const char *username, const char *chroot_dir)
{
...
            if (initgroups(pw->pw_name, pw->pw_gid) != 0 ||
               setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) {
                    fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n",
                        username, 
                        (unsigned long)pw->pw_uid,
                        (unsigned long)pw->pw_gid,
                        pcap_strerror(errno));
                    exit(1);
            }
...
}

2
Correct. initgroups, setgid, setuid(Enfin!) Est précisément le paradigme droit sur unix, et doit toujours être suivi. De plus, une fonction "droproot" responsable vérifie que son uid et son gid ont bien été définis, même si les trois fonctions principales ont réussi.
Nicholas Wilson

3

Vous pouvez exécuter des commandes en tant que d'autres utilisateurs en utilisant su:

 su USERNAME -c COMMAND

S'exécutera COMMANDavec les privilèges accordés à USER.


Notez que, par défaut, suutilisera l'interpréteur de commandes de l'utilisateur cible pour exécuter la commande. En revanche, le comportement par défaut de sudoest de traiter le COMMANDcomme un programme autonome, c'est-à-dire exécuté l'environnement actuel. Bien sûr, ces comportements par défaut peuvent être modifiés avec divers commutateurs et variables d'environnement.


Il semble que sucela ne fonctionne pas si USERNAME n'a pas de shell défini (ou /bin/false) alors que sudo fonctionne.
Aif

1
@Aif Si l'utilisateur n'est pas autorisé à exécuter des commandes interactives, le comportement par défautsu le reflétera. Cependant, on peut toujours remplacer cela en utilisant le -scommutateur. Notez que le but de suest d'imiter le comportement d'un utilisateur donné - qui est normalement influencé par son shell. En revanche, sudoignorerait (par défaut) le paramètre de shell de l'utilisateur cible.
rozcietrzewiacz

Non, veuillez ne pas exécuter les choses en utilisant un shell simplement pour supprimer les privilèges. Cela laisse beaucoup trop de contrôle à un attaquant, lisant divers fichiers de configuration que vous ne voulez pas toucher.
Nicholas Wilson

2

Pour supprimer des privilèges, vous avez besoin d'un utilisateur non root pour accéder à. Ensuite, il suffit de passer à cet utilisateur:

#define UNPRIV_UID  48
#define UNPRIV_GID  48

if (getuid() == 0) { // we are root
    // setting UID/GID requires root privileges, so if you don't set
    // the GID first, you won't be able to do it at all.
    if (setgid(UNPRIV_GID)!=0) die("Failed to set nonroot GID");
    if (setuid(UNPRIV_UID)!=0) die("Failed to set nonroot UID");
}

ASSERT(getuid() != 0); 

Notez que cela se fait dans le programme lui-même, plutôt que dans un script wrapper. De nombreux programmes nécessitent des privilèges root dans un but spécifique (par exemple pour se lier à un port de faible nombre), mais n'ont pas besoin de root après cela. Ces programmes démarrent donc en tant que root, mais abandonnent ensuite les privilèges une fois qu'ils ne sont plus nécessaires.

Si vous n'avez pas du tout besoin des privilèges root, alors ne l'exécutez pas en tant que root. Par exemple:

# Change this:
myprog -C /my/config/file

# To this:
sudo -u someuser myprog -C /my/config/file
# Or this
su someuser -c "myprog -C /my/config/file"

1
Notez que cela permet au processus de récupérer les privilèges s'il le souhaite! La setuidfonction définit uniquement l' UID effectif , pas le véritable UID. Vous devez utiliser setreuidsi vous ne voulez pas que le processus puisse récupérer les privilèges. (Et le code ci-dessus ne traite pas non plus des privilèges de groupe supplémentaires. Il ne convient que pour lancer du code principalement fiable.)
David Schwartz

Le code @David Schwartz a été intentionnellement simplifié pour montrer le mécanisme utilisé.
tylerl

Si vous voulez simplifier le code critique pour la sécurité, vous devez indiquer très clairement que c'est ce que vous faites. Et vous devriez dire des choses comme "c'est juste une question de" quand ce n'est pas le cas.
David Schwartz

2
@David En fait, setuid()définit des ID utilisateur réels et enregistrés; vous pensez peut-être seteuid(). Tous les systèmes ne l'ont pas setreuid(), il ne peut donc pas être utilisé un peu partout. La sémantique exacte de setuid()est compliquée, mais si vous avez euid 0, vous serez en mesure de supprimer tous les privilèges d'ID utilisateur traditionnels avec setuid(). La plus grande omission dans cette réponse est que initgroupsou setgroupsdoit être appelé ainsi que setgidet setuid, et que des affirmations plus approfondies doivent être faites à la fin.
Nicholas Wilson

0

Si vous exécutez un exécutable différent, c'est-à-dire que vous appelez execveou une autre famille de execfonctions, peut-être indirectement via une fonction comme systemou popen, et que le processus enfant doit s'exécuter sans privilèges dès le début, alors le plus simple est d'obtenir un shell impliqué, et appeler su. Voici un aperçu de l'apparence du code en Perl, montrant la citation nécessaire pour:

$shell_command = quotemeta($path_to_executable) . " --option";
$shell_command =~ s/'/'\\''/; # protect single quotes for the use as argument to su
$su_command = sprintf("su -c '%s' %s", $shell_command, quotemeta($user_name));
open(PIPE, "$su_command |") or die;

Si le processus enfant doit démarrer en tant que root mais supprimer les privilèges plus tard, consultez le code dans cette réponse , qui illustre comment rétrograder les privilèges dans un processus.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.