El bit de permiso setuid
indica a Linux que ejecute un programa con el id de usuario efectivo del propietario en lugar del ejecutor:
> cat setuid-test.c
#include <stdio.h>
#include <unistd.h>
int main(int argc, char** argv) {
printf("%d", geteuid());
return 0;
}
> gcc -o setuid-test setuid-test.c
> ./setuid-test
1000
> sudo chown nobody ./setuid-test; sudo chmod +s ./setuid-test
> ./setuid-test
65534
Sin embargo, esto sólo se aplica a los ejecutables; los shell scripts ignoran el bit setuid:
> cat setuid-test2
#!/bin/bash
id -u
> ./setuid-test2
1000
> sudo chown nobody ./setuid-test2; sudo chmod +s ./setuid-test2
> ./setuid-test2
1000
Wikipedia dice:
Debido a la mayor probabilidad de fallos de seguridad, muchos sistemas operativos ignoran el atributo setuid cuando se aplica a scripts de shell ejecutables.
Asumiendo que estoy dispuesto a aceptar esos riesgos, ¿hay alguna forma de decirle a Linux que trate el bit setuid de la misma forma en los shell scripts que en los ejecutables?
Si no, ¿hay alguna solución común para este problema? Mi solución actual es añadir una entrada sudoers
para permitir que ALL
ejecute un script dado como el usuario con el que quiero que se ejecute, con NOPASSWD
para evitar la petición de contraseña. Las principales desventajas de esto es la necesidad de una entrada sudoers
cada vez que quiero hacer esto, y la necesidad de que la persona que llama a sudo some-script
en lugar de sólo some-script
.
Una forma de resolver este problema es llamar al script de shell desde un programa que pueda utilizar el bit setuid.
Es algo como sudo.
Por ejemplo, aquí está cómo usted lograría esto en un programa de C:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
setuid( 0 ); // you can set it at run time also
system( "/home/pubuntu/setuid-test2.sh" );
return 0;
}
Guárdalo como setuid-test2.c. compilar Ahora haz el setuid en este binario de programa:
su - nobody
[enter password]
chown nobody:nobody a.out
chmod 4755 a.out
Ahora, deberías poder ejecutarlo, y verás que tu script se ejecuta con permisos nobody.
Pero aquí también hay que hardcode la ruta de script o pasarlo como arg línea de comandos para arriba exe.
Si quieres evitar llamar a sudo some_script
puedes simplemente hacer:
#!/ust/bin/env sh
sudo /usr/local/scripts/your_script
Los programas SETUID necesitan ser diseñados con extremo cuidado ya que se ejecutan con privilegios de root y los usuarios tienen un gran control sobre ellos. Necesitan comprobar todo. No se puede hacer con scripts porque:
sed
, awk
, etc.Tenga en cuenta que sudo
proporciona alguna comprobación de sanidad pero no es suficiente - compruebe cada línea de su propio código.
Como última nota: considere el uso de capacidades. Te permiten dar a un proceso que se ejecuta como usuario privilegios especiales que normalmente requerirían privilegios de root. Por ejemplo, mientras que ping
necesita manipular la red, no necesita tener acceso a ficheros. Sin embargo, no estoy seguro de si se heredan.
Puedes crear un alias para sudo + el nombre del script. Por supuesto, eso es aún más trabajo de configurar, ya que entonces usted tiene que configurar un alias, también, pero le ahorra tener que escribir sudo.
Pero si no te importan los horribles riesgos de seguridad, usa un shell setuid como intérprete para el script de shell. No sé si te funcionará, pero supongo que sí.
**Permíteme decir que no te aconsejo hacer esto, sin embargo. Sólo lo menciono con fines educativos ;-)