setuid y setgid son unos permisos especiales, también llamados los sticky bits, que se les pueden asignar a los programas ejecutables para que se ejecuten con los permisos del propietario y no del usuario que los ejecuta. Esto sirve para, por ejemplo, que cualquier usuario ejecute el comando ping aunque éste necesite privilegios de administrador, que es el propietario. En GNU/Linux, y en Unix, estos bits se ignoran cuando se aplican a directorios.

Ejecutar un comando como si fuésemos otro usuario, especialmente como si fuésemos el administrador, suena peligroso... para el administrador. El problema viene porque si uno de éstos programas sufre un buffer overflow, el usuario podría ejecutar código arbitrario con privilegios de administrador.

Para cambiar estos permisos con chmod debemos utilizar el byte alto. El valor en octal que debemos usar es 4 para el setuid y 2 para el setgid. Si queremos poner los dos utilizaremos el 6.

Por ejemplo, activar el setuid (4) y darle permisos de ejecución, lectura y escritura para el propietario (7), y sólo de lectura para el grupo y el resto (4) sería:

$ chmod 4744 myelf

Si sólo quisiéramos cambiarle los permisos a un archivo para que tenga alguno de estos bits activados:

$ chmod u+s myelf
$ chmod g+s myelf
$ chmod ug+s myelf

Para quitárselos:

$ chmod u-s myelf
$ chmod g-s myelf
$ chmod ug-s myelf

Para mostrar los archivos con setuid o setgid que hay en el sistema, accesibles para el usuario con el que estamos, evitando mostrar los avisos de que no tenemos permisos de entrar en según qué direcctorios, ejecutamos:

$ find / -type f \( -perm -4000 -o -perm -2000 \) -print 2>/dev/null 1>stickybit.txt &
$ tail -f stickybit.txt

/bin/mount
/bin/fusermount
/bin/su
/bin/umount
/bin/ping6
/bin/ping
...

En la Wikipedia, podemos ver un pequeño programa en C que nos muestra esta diferencia entre el uid del usuario y del propietario:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(void) {
    printf(
        "Real      UID = %d\n"
        "Effective UID = %d\n"
        "Real      GID = %d\n"
        "Effective GID = %d\n",
        getuid (),
        geteuid(),
        getgid (),
        getegid()
    );
    return 0;
}

Vamos a probarlo. El código de este programa está en el archivo printid.c:

$ id -u
1000
$ sudo id -u
0
$ sudo gcc -Wall printid.c -o printid
$ sudo chmod ug+s printid
$ ls -l printid
-rwsr-sr-x 1 root root 7249 2011-02-28 13:17 printid
$ ./printid
Real      UID = 1000
Effective UID = 0
Real      GID = 1000
Effective GID = 0

Entradas relacionadas


Published

Category

admin

Tags

Contacto