Descartar privilegios de proceso

12

Tengo un proceso que comienza con un damon que se ejecuta como root, ahora quiero "degradar" los privilegios de este proceso a los de su usuario promedio. es posible? Si es así, ¿cómo?

PD: ejecutar unix en una mac

Samantha Catania
fuente

Respuestas:

5

El proceso en sí tiene que llamar a setuid (2). También debe investigar ejecutarlo dentro de chroot (8) si aún no lo ha hecho. Hasta donde yo sé, no hay forma de que root cambie el uid de otro proceso.

Si la razón por la que lo está ejecutando como root es para vincular puertos, le sugiero que lo ejecute como un usuario normal en un puerto superior y use ipfw (8) en OS X para reenviar el puerto 80/443 / etc al puerto superior:

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

polinomio
fuente
Puse setuid (uid) en mi programa que se ejecuta como root pero necesito que se ejecute como un usuario normal y no sucede nada, es decir, continúa ejecutándose como root
Samantha Catania
Probablemente necesite detectar los errores de allí (tal vez esté obteniendo un EINVAL para el uid). Su improbable setuid está roto en su máquina. Puede verificarlo si apache se ejecuta como _www. Documentos del programador: developer.apple.com/library/mac/#documentation/Darwin/Reference/…
polinomio
tienes razón, da un error de sintaxis del uid a pesar de que es correcto. ¿Es este el formato correcto setuid (500)?
Samantha Catania
encontré el problema: estaba tratando de ejecutar el comando a través del sistema () pero simplemente ejecuté el comando, funcionó y resolví mi problema; gracias por la ayuda
Samantha Catania
No. Este no es un buen consejo: llamar setuid()solo no es suficiente.
Nicholas Wilson
13

sudo tcpdump -Z usa initgroups (3), setgid (2) y setuid (2) para eliminar los privilegios de raíz de su propio proceso.

# 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);
            }
...
}
phron
fuente
2
Correcto. initgroups, setgid, setuid(Última!) Es precisamente el paradigma de la derecha en UNIX, y siempre se debe seguir. Además, una función responsable de "droproot" verifica que su uid y gid realmente se hayan configurado, incluso si las tres funciones principales devolvieron el éxito.
Nicholas Wilson
3

Puede ejecutar comandos como otros usuarios usando su:

 su USERNAME -c COMMAND

Se ejecutará COMMANDcon privilegios reducidos a USER.


Tenga en cuenta que, de forma predeterminada, suutilizará el intérprete de shell del usuario objetivo para ejecutar el comando. Por el contrario, el comportamiento predeterminado de sudoes tratar el COMMANDcomo un programa independiente, es decir, ejecutar el entorno actual. Por supuesto, estos comportamientos predeterminados se pueden cambiar con varios modificadores y variables de entorno.

rozcietrzewiacz
fuente
Parece suque no funciona si USERNAME no tiene un shell definido (o /bin/false) mientras que sudo sí funciona.
Aif
1
@Aif Si el usuario no puede ejecutar comandos interactivos, el comportamiento predeterminadosu lo reflejará. Sin embargo, uno siempre puede anular eso usando el -sinterruptor. Tenga en cuenta que el propósito de sues imitar el comportamiento de un usuario dado, que normalmente está influenciado por su shell. Por el contrario, sudoignoraría (por defecto) la configuración del shell del usuario objetivo.
rozcietrzewiacz
No, por favor no ejecute cosas usando un shell simplemente para eliminar privilegios. Eso deja demasiado en el control de un atacante, leyendo en varios archivos de configuración que no desea tocar.
Nicholas Wilson
2

Para eliminar privilegios, necesita un usuario que no sea root para acceder. Entonces es solo cuestión de cambiar a ese usuario:

#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); 

Tenga en cuenta que esto se realiza dentro del propio programa , en lugar de hacerlo en un script de contenedor. Muchos programas requieren privilegios de root para algún propósito específico (por ejemplo, para enlazar a un puerto de número bajo), pero no necesitan root después de eso. Entonces, estos programas comenzarán como root, pero luego abandonarán los privilegios una vez que ya no sean necesarios.

Si no necesita privilegios de root, simplemente no lo ejecute como root. P.ej:

# 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"
tylerl
fuente
1
Tenga en cuenta que esto permite que el proceso recupere los privilegios si así lo desea. La setuidfunción solo establece el UID efectivo , no el UID real. Debería usarlo setreuidsi no desea que el proceso pueda recuperar los privilegios. (Y el código anterior no tratar con privilegios de grupo suplementarios ya sea Es adecuado sólo para el lanzamiento de código sobre todo de confianza..)
David Schwartz
El código de @David Schwartz se simplificó intencionalmente para mostrar el mecanismo utilizado.
tylerl
Si va a simplificar el código crítico para la seguridad, debe dejar muy claro que esto es lo que está haciendo. Y deberías decir cosas como "es solo cuestión de" cuando no lo es.
David Schwartz
2
@David En realidad, setuid()establece usuarios reales y guardados; usted puede estar pensando seteuid(). No todos los sistemas tienen setreuid(), por lo que no se puede usar en todas partes. La semántica exacta de setuid()se complica, pero si tiene euid 0, podrá eliminar todos los privilegios de identificación de usuario tradicionales setuid(). La mayor omisión en esta respuesta es que initgroupso setgroupsdebe llamarse así como setgidy setuid, y que al final deben hacerse afirmaciones más exhaustivas.
Nicholas Wilson
0

Si está ejecutando un ejecutable diferente, es decir, está llamando a execveotra función de la execfamilia, tal vez indirectamente a través de una función como systemo popen, y el proceso secundario debería ejecutarse sin privilegios desde el principio, entonces la forma más simple es obtener un shell involucrado, y llame su. Aquí hay una descripción general de cómo se vería el código en Perl, mostrando las citas necesarias para:

$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 el proceso secundario necesita comenzar como root pero luego elimina los privilegios, vea el código en esta respuesta , que ilustra cómo degradar los privilegios en un proceso.

Gilles 'SO- deja de ser malvado'
fuente