Chamar um script a partir de um programa de raiz C setuid - script não executar como root
Pergunta
Eu preciso executar um script como root (sudo sem senha ou su não viável) e desde que você não pode setuid um script em Linux, eu pensei em chamá-lo a partir de um executável e fazer it 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
$
Isso funciona - como em executa o script corretamente -., Mas o script é executado como o usuário que executa "./wrapper"
Por quê? E como implementar corretamente essa?
Obrigado!
Solução
Uma vez que o bit suid
em executáveis ??só muda a UID efetivo (EUID) o executável será executado como, e não o real UID (RUID) que getuid()
retornos, e para além da restrição à suid
interpretada de scripts (qualquer início executável com "#!
"), alguns escudos como bash
como uma medida de segurança extra vai definir a volta EUID ao RUID neste caso, você precisará usar o setuid(0)
chamada no código C antes de executar o script.
Veja as páginas man
do setuid
, seteuid
, getuid
e geteuid
para aprender a semântica exata dos UIDs reais e eficazes.
( ATENÇÃO ) Evidentemente, este é um ponto apropriado mencionar que a restrição em scripts suid
em muitos sistemas UNIX, conchas e intérpretes, estão lá por um motivo, que é que se o script não é muito cuidadoso sobre saneantes sua entrada e o estado do ambiente quando ele é executado, eles são perigosos e podem ser exploradas para a escalada de segurança. Portanto, muito cuidado ao fazer isto. Defina o acesso ao seu script e invólucro tão rigorosas quanto você puder, só permitem que este script muito específico que você pretende ser executado, e limpar o ambiente dentro de seu programa C antes de iniciar o script, definir variáveis ??de ambiente tais como PATH
para conter exatamente o que é necessário na ordem certa e há diretórios que são graváveis ??para os outros.
Outras dicas
Outra coisa a notar aqui é que a limitação aqui é de festa e não o próprio sistema * nix. Bash realmente fazer verificações em scripts SUID apenas executá-los com EUID raiz. Se você pegar conchas mais velhos, muitas vezes você vai conseguir o que queria sair da caixa. Por exemplo, sh não faz esse tipo de verificações:
$ 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
Com 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
Ainda assim, a resposta de Tom é geralmente o caminho a percorrer para fazer um wrapper para programas SUID root
Adicione o setuid (0) no script e compilá-lo. Ele deve funcionar depois disso.
$ 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
$
Os exemplos são terrivelmente inseguro e permite que qualquer pessoa com dois pedaços de conhecimento para executar qualquer programa que eles querem que o usuário setuid.
Nunca passar por um shell a menos que você higienizar o ambiente em primeiro lugar, a maioria dos exemplos mostrados aqui são vulneráveis ??a ter IFS e set PATH antes de executá-lo.
Por que não é sudo viável? Evita fúria falhas de segurança, tais 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$
Devido ao ambiente não sendo devidamente higienizados, por exemplo neste caso:
export echo='() { builtin echo heh heh; }'
sudo sanitizes Neste caso, e talvez outros casos de ponta e Armadilhas que seriam bem para não escrever em um invólucro suid personalizado.