
Estou tentando executar o programa compilado C++ como root, enquanto sou outro usuário.
O programa foi executado com sucesso, mas como um usuário normal, não como root.
Porém, como diz a internet, chmod u+s
o comando faz com que ele seja executado como proprietário (no meu caso - root).
O programa é uma linha simples system(argv[1])
, que executará tudo dentro do argumento da linha de comando.
Por exemplo - A saída para whoami
retorna meu usuário, não o root.
Também tentar listar o conteúdo /root
acaba em "Permissão negada".
Permissões do arquivo -
-rwsr-xr-x 1 root root 16608 Aug 25 15:20 test
Neste momento tentei dar permissões ao arquivo 4755
(sem sorte).
Mover o arquivo /root
também não teve sorte.
Responder1
A chamada system() usa a execl()
chamada do sistema para criar um novo processo shell. Mas a chamada do sistema ignora o ID do usuário efetivo e retorna o erro EPERM (permissão negada).
Isso ocorre porque os shells do Linux não herdam o bit seteuid. Por que? Bem, porque existem preocupações reais sobre a execução de um script com o ID de usuário efetivo como root. Para mais leituras sobre o tema vejaaqui.
É possível executar um shell que atue no UID efetivo passando o -p
parâmetro. Na sh
página de manual:
-p privado Não tente redefinir o uid efetivo se ele não corresponder ao uid. Isto não é definido por padrão para ajudar a evitar o uso incorreto por programas root setuid via system(3) ou popen(3).
É claro que a restrição não se aplica a chamadas de sistema. Como demonstração, este programa C tenta listar /root usando system()
e, em seguida, faz o mesmo usando as chamadas do sistema opendir()
e .readdir()
Se o binário pertencer a root com o ID do usuário set definido, um usuário não-root executando o programa resultará na falha da primeira listagem /root, a segunda (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"));
}