Ho un processo che viene avviato da un damon in esecuzione come root, ora voglio "declassare" i privilegi di questo processo a quelli dell'utente medio. È possibile? Se si come?
PS: esegue unix su un mac
Ho un processo che viene avviato da un damon in esecuzione come root, ora voglio "declassare" i privilegi di questo processo a quelli dell'utente medio. È possibile? Se si come?
PS: esegue unix su un mac
Risposte:
Il processo stesso deve chiamare setuid (2). Dovresti anche investigare eseguendolo all'interno di chroot (8) se non lo sei già. Per quanto ne so, non c'è modo per root di cambiare l'UID di un altro processo.
Se il motivo per cui lo stai eseguendo come root è il bind delle porte, ti suggerirei di eseguirlo come un normale utente su una porta superiore e di usare ipfw (8) su OS X per inoltrare la porta 80/443 / etc alla porta superiore:
http://support.crashplanpro.com/doku.php/recipe/forward_port_443_to_pro_server_on_mac_osx
setuid()
da soli non è assolutamente sufficiente.
sudo tcpdump -Z
usa initgroups (3), setgid (2) e setuid (2) per eliminare i privilegi di root del proprio processo.
# 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);
}
...
}
initgroups
, setgid
, setuid
(Finalmente!) È proprio il paradigma destra su UNIX, e dovrebbe sempre essere seguita. Inoltre, una funzione "droproot" responsabile verifica che i suoi uid e gid siano stati effettivamente impostati, anche se tutte e tre le funzioni primarie hanno dato esito positivo.
Puoi eseguire comandi come altri utenti usando su
:
su USERNAME -c COMMAND
Funzionerà COMMAND
con i privilegi rilasciati a USER
.
Si noti che, per impostazione predefinita, su
verrà utilizzato l'interprete della shell dell'utente di destinazione per eseguire il comando. Al contrario, il comportamento predefinito di sudo
è di trattare il COMMAND
programma come un programma autonomo, che viene eseguito l'ambiente corrente. Naturalmente questi comportamenti predefiniti possono essere modificati con vari switch e variabili d'ambiente.
su
che non funzioni se USERNAME non ha una shell definita (o /bin/false
) mentre sudo funziona.
su
lo rifletterà. Tuttavia, si può sempre ignorare quello usando l' -s
interruttore. Si noti che lo scopo di su
è imitare il comportamento di un determinato utente, che è normalmente influenzato dalla sua shell. Al contrario, sudo
(per impostazione predefinita) ignorerebbe l'impostazione della shell dell'utente di destinazione.
Per eliminare i privilegi, è necessario un utente non root a cui accedere. Quindi è solo una questione di passare a quell'utente:
#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);
Si noti che ciò avviene all'interno del programma stesso, piuttosto che in uno script wrapper. Molti programmi richiedono i privilegi di root per uno scopo specifico (ad es. Per associarsi a una porta con numero basso), ma dopo non hanno bisogno di root. Quindi questi programmi inizieranno come root, ma poi lasceranno cadere i privilegi quando non saranno più necessari.
Se non hai affatto bisogno dei privilegi di root, non eseguirlo come root. Per esempio:
# 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"
setuid
funzione imposta solo l' UID effettivo , non l'UID reale. Dovresti usarlo setreuid
se non vuoi che il processo sia in grado di recuperare i privilegi. (E il codice sopra non si occupa nemmeno dei privilegi di gruppo supplementari. È adatto solo per il lancio di codice per lo più fidato.)
setuid()
imposta userid reali e salvati; potresti pensare seteuid()
. Non tutti i sistemi hanno setreuid()
, quindi non può essere usato abbastanza dappertutto. La semantica esatta di setuid()
è complicata, ma se hai euid 0, sarai in grado di eliminare tutti i privilegi di id utente tradizionali setuid()
. La più grande omissione in questa risposta è che initgroups
o setgroups
deve essere chiamata così come setgid
e setuid
, e che alla fine dovrebbero essere fatte affermazioni più approfondite.
Se stai eseguendo un altro eseguibile, cioè stai chiamando execve
o un'altra della exec
famiglia di funzioni, forse indirettamente attraverso una funzione come system
o popen
, e il processo figlio dovrebbe essere eseguito senza privilegi dall'inizio, allora il modo più semplice è ottenere un shell coinvolta e chiama su
. Ecco una panoramica di come potrebbe apparire il codice in Perl, mostrando le quotazioni necessarie per:
$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;
Se il processo figlio deve iniziare come root ma eliminare i privilegi in un secondo momento, vedere il codice in questa risposta , che illustra come eseguire il downgrade dei privilegi in un processo.