programar - script linux ejemplos
Llamar a un script desde un programa setuid root C: el script no se ejecuta como root (5)
Necesito ejecutar un script bash como root (sudo o su no viable sin contraseña) y como no se puede establecer un script en Linux, pensé en llamarlo desde un ejecutable y hacer que fuera setuid:
$ cat wrapper.c
int main(void)
{
system("/bin/bash ./should_run_as_root.sh");
}
$ gcc -o wrapper wrapper.c
$ sudo chown root wrapper
$ sudo chmod ug+s wrapper
$ ll wrapper
-rwsr-sr-x 1 root users 6667 2009-02-17 11:11 wrapper
$
Esto funciona, al igual que ejecutar el script correctamente, pero el script se ejecuta como el usuario que ejecuta "./wrapper".
¿Por qué? ¿Y cómo implementar esto correctamente?
¡Gracias!
Como el bit de suid
en ejecutables solo cambia el UID efectivo (EUID), el ejecutable se ejecutará como, y no el UID real (RUID) que getuid()
, y además de la restricción en scripts interpretados suid
(cualquier ejecutable que comience con " #!
"), algunos shells como bash
como una medida de seguridad adicional establecerán el EUID de nuevo en el RUID en este caso, deberá usar el setuid(0)
llamada setuid(0)
en el código C antes de ejecutar el script.
Consulte las páginas man
de setuid
, seteuid
, getuid
y geteuid
para conocer la semántica exacta de los UID reales y efectivos.
( ADVERTENCIA ) Por supuesto, este es un punto apropiado para mencionar que la restricción en scripts suid
en muchos sistemas Unix, shells e intérpretes, está ahí por una razón, que es que si el script no es muy cuidadoso para desinfectar su entrada y el estado del entorno cuando se ejecuta, son peligrosos y pueden aprovecharse para una escalada de seguridad. Así que ten mucho cuidado al hacer esto. Establezca el acceso a su secuencia de comandos y contenedor lo más estrictamente posible, solo permita este script muy específico que desea ejecutar, y borre el entorno dentro de su programa C antes de iniciar el script, configurando variables de entorno como PATH
para que contengan exactamente es necesario en el orden correcto y no hay directorios que puedan escribirse a otros.
Otra cosa a tener en cuenta aquí es que la limitación aquí es de bash y no del sistema * nix en sí mismo. Bash realmente realiza verificaciones en los scripts SUID para ejecutarlos solo con la raíz EUID. Si toma conchas más viejas, a menudo obtendrá lo que quería de la caja. Por ejemplo, sh no hace este tipo de verificaciones:
$ cat wrapper.c
int main(void)
{
system("/bin/sh -c whoami");
}
$ ls -l wrapper
-rwsr-sr-x 1 root users 8887 Feb 17 14:15 wrapper
$ ./wrapper
root
Con bash:
$ cat wrapper.c
int main(void)
{
system("/bin/bash -c whoami");
}
$ ls -l wrapper
-rwsr-sr-x 1 root users 8887 Feb 17 14:18 wrapper
$ ./wrapper
skinp
Aún así, la respuesta de Tom es generalmente el camino a seguir para crear un contenedor para los programas raíz SUID
Agregue el setuid (0) en el script y complételo. Debería funcionar después de esto.
$ cat wrapper.c
int main(void)
{
setuid(0);
system("/bin/bash ./should_run_as_root.sh");
}
$ gcc -o wrapper wrapper.c
$ sudo chown root wrapper
$ sudo chmod ug+s wrapper
$ ll wrapper
-rwsr-sr-x 1 root users 6667 2009-02-17 11:11 wrapper
$
¿Por qué sudo no es viable? Evita feroces agujeros de seguridad tales como:
bash-3.2$ cat test
#!/bin/bash
echo ima shell script durp durp
bash-3.2$ chmod +x test
bash-3.2$ ./test
heh heh
bash-3.2$
Debido a que el medio ambiente no se desinfecta correctamente, por ejemplo en este caso:
export echo=''() { builtin echo heh heh; }''
sudo desinfecta este caso, y tal vez otros casos extremos y errores que sería mejor no escribir en un contenedor de suid personalizado.
Los ejemplos son terriblemente inseguros y permiten a cualquier persona con dos bits de conocimiento ejecutar cualquier programa que desee como usuario de setuid.
Nunca pase por un intérprete de órdenes a menos que primero desinfecte el entorno, la mayoría de los ejemplos que se muestran aquí son vulnerables a tener IFS y PATH configurados antes de ejecutarlo.