
Estoy intentando ejecutar el programa compilado en C++ como root, mientras soy otro usuario.
El programa se ejecuta correctamente, pero como usuario normal, no como root.
Sin embargo, como dice Internet, chmod u+s
el comando hace que se ejecute como propietario (en mi caso, root).
El programa es una línea simple system(argv[1])
, que ejecutará todo lo que esté dentro del argumento de la línea de comando.
Por ejemplo: la salida para whoami
devuelve mi usuario, no la raíz.
También intentar enumerar el contenido /root
termina en "Permiso denegado".
Permisos del archivo -
-rwsr-xr-x 1 root root 16608 Aug 25 15:20 test
En este momento intenté otorgar permisos al archivo 4755
(no tuve suerte).
Mover el archivo /root
tampoco fue una suerte.
Respuesta1
La llamada system() utiliza la execl()
llamada al sistema para crear un nuevo proceso de shell. Pero la llamada al sistema ignora la identificación de usuario efectiva y devuelve un error EPERM (permiso denegado).
Esto se debe a que los shells de Linux no heredan el bit seteuid. ¿Por qué? Bueno, porque existen preocupaciones reales sobre la ejecución de un script con la identificación de usuario efectiva como root. Para obtener más información sobre el tema, consulteaquí.
Es posible ejecutar un shell que actúa sobre el UID efectivo pasando el -p
parámetro. Desde la sh
página de manual:
-p privado No intente restablecer el uid efectivo si no coincide con el uid. Esto no está configurado de forma predeterminada para ayudar a evitar el uso incorrecto por parte de los programas raíz setuid a través de system(3) o popen(3).
Por supuesto, la restricción no se aplica a las llamadas al sistema. Como demostración, este programa en C intenta enumerar /root usando system()
y luego hace lo mismo usando las llamadas al sistema opendir()
y readdir()
.
Si el binario es propiedad de root con el ID de usuario establecido, un usuario no root que ejecute el programa provocará que el primer listado /root falle y el segundo (usando display_dir()
works.
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<dirent.h>
#include<errno.h>
int display_dir(const char *dirname)
{
DIR *dp = opendir(dirname);
struct dirent *sd=NULL;
if (!dp) return(errno);
while ((sd = readdir(dp)) != NULL)
{
printf("%s\n", sd->d_name);
}
closedir(dp);
return 0;
}
int main()
{
system("ls /root");
printf("Display returned %d\n", display_dir("/root"));
}