Membresías grupales y procesos setuid / setgid

10

Procesos que reducen los privilegios a través de setuid()y setgid()no parecen heredar las pertenencias a grupos del uid / gid que establecen.

Tengo un proceso de servidor que debe ejecutarse como root para abrir un puerto privilegiado; después de eso se reduce a un uid / gid no privilegiado específico, 1 , por ejemplo, el del usuario foo(UID 73). El usuario fooes miembro del grupo bar:

> cat /etc/group | grep bar
bar:x:54:foo

Por lo tanto, si inicio sesión como foo, puedo leer un archivo /test.txtcon estas características:

> ls -l /test.txt
-rw-r----- 1 root bar 10 Mar  8 16:22 /test.txt

Sin embargo, el siguiente programa C (compilar std=gnu99), cuando se ejecuta root:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main (void) {
    setgid(73);
    setuid(73);
    int fd = open("/test.txt", O_RDONLY);
    fprintf(stderr,"%d\n", fd);
    return 0;
}   

Siempre informa Permiso denegado . Me imagino que esto tiene que ver con que es un proceso que no es de inicio de sesión, pero de alguna manera afecta a la forma en que se supone que funcionan los permisos.


1. Lo que a menudo es SOP para servidores, y creo que debe haber una forma de evitarlo, ya que encontré un informe de alguien haciéndolo con apache. Apache se ha agregado al grupo de audio y aparentemente puede usar el sistema de sonido. Por supuesto, esto probablemente ocurre en una bifurcación y no en el proceso original, pero de hecho, el caso es el mismo en mi contexto (es un proceso secundario bifurcado después de la llamada setuid).

encerrada dorada
fuente
Cambia las llamadas setuid()/ setgid().
vonbrand
@vonbrand ROTFL Pensé que me iba a dar una palmada facial allí, pero el mismo resultado, así que editaré la pregunta para eliminar el arenque rojo.
Ricitos
1
Si usa en setgid(54)lugar de setgid(73)(como en /etc/groups, el grupo bartiene gid 54), ¿funciona?
lgeorget
@lgeorget Claro, pero eso frustra el propósito. El proceso necesita su propio GID por otras razones, y de la misma manera, esos archivos deben tener los permisos que tienen. Es por eso que la membresía en grupos en plural es necesaria, por ejemplo, ¿qué pasa si tiene dos usuarios que necesitan hacer esto? Tenga en cuenta que no se puede setuid()volver después de hacerlo ... pero, hmmm ... creo que se puede con seteuid()...
GOLDILOCKS
1
Mi pregunta era asegurarme de que no hubiera otro problema sutil oculto en alguna parte. :-)
lgeorget

Respuestas:

14

El problema es eso setuidy setgid no son suficientes para darle a su proceso todas las credenciales que necesita. Las autorizaciones de un proceso dependen de

  • su UID
  • su GID
  • sus grupos suplementarios
  • sus capacidades

Consulte man 7 credentialspara obtener una descripción más detallada. Entonces, en su caso, el problema es que configuró correctamente el UID y el GID, pero no configuró los grupos suplementarios del proceso. Y el grupo bartiene GID 54, no 73, por lo que no se reconoce como grupo en el que se encuentra su proceso.

Deberías hacer

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <grp.h>

int main (void) {
    gid_t supplementary_groups[] = {54};

    setgroups(1, supplementary_groups);
    setgid(73);
    setuid(73);
    int fd = open("/test.txt", O_RDONLY);
    fprintf(stderr,"%d\n", fd);
    return 0;
}  
lgeorget
fuente
1
Esa fue una pregunta interesante que merece más votos positivos porque en realidad podría ser útil para mucha gente. :-)
lgeorget
Entonces estaba teniendo un problema similar con los puertos seriales. Implementé esto para el dialoutgrupo y funcionó por primera vez.
tl8
0

OK, recorrí un poco la red. Al principio pensé que APUE tendría todas las respuestas, pero me equivoqué. Y mi copia (edición anterior) está funcionando, así que ... El capítulo 5 del Manual de Administración de Unix y Linux parece prometedor, pero no lo tengo (solo una copia de las dos primeras ediciones, también en funcionamiento).

Los pocos recursos que he encontrado (google para "daemon writing unix") hablan sobre pasos importantes, como la forma de disociarse del tty, etc. Pero nada sobre UID / GID. Curiosamente, ni siquiera la extensa colección HOWTO en http://tldp.org parece tener detalles. Sólo excetion es de Jason Short Vamos a un demonio de Linux - parte I . Los detalles completos de cómo SUID / SGID y todo ese desorden funcionan es el SUID de Chen, Wagner y Dean desmitificado (un documento en USENIX 2002). Pero tenga cuidado, Linux tiene un UID adicional, el FSUID (consulte las Notas de incompatibilidad de Unix de Wolter : Funciones de configuración de UID para una discusión).

Demoniar un proceso definitivamente no es para los débiles de corazón. Consideraciones generales de seguridad se dan en la programación segura de D. Wheeler para Linux y Unix HOWTO - Creación de software seguro . Systemd promete simplificar la mayor parte de eso (y así reducir el margen de errores que conducen a problemas de seguridad), consulte el manual del demonio .

vonbrand
fuente
1
La pregunta no es sobre la demonización. Ha confundido el bit SUID (otorgando a un proceso los permisos del propietario de su ejecutable) setuid(), lo que permite que el proceso cambie su UID arbitrariamente. SUID generalmente está destinado a permitir una escalada de permisos (no privilegiados -> privilegiados), mientras setuid()que solo puede hacer lo contrario.
Ricitos