Setuid Em Shell Scripts

Introdução

Setuid (também conhecido como Set-User-Id ou SUID) é um bit de permissão que é capaz de mudar os privilégios de execução de um arquivo executável. Seu uso deve ser bastante moderado, pois algus bugs em programas que o habilita podem colocar todo o sistema em risco.

Visando isso e para manter o uso do setuid bit o mais limitado possível, os desenvolvedores do unix e derivados resolveram desativar esse bit de arquivos script. Desse modo não é possível executar um script como root sem que você seja de fato o usuário root.

Nesse post veremos um “workaround” para executarmos um shell script com setuid.

Testando Setuid em Shellscript

Salve o seguinte script como teste.sh e depois dê permissão de execução para ele:

#!/bin/bash
cat /etc/shadow

Como sabemos o arquivo /etc/shadow armazena as senhas criptografadas dos usuários do sistema e por isso somente o root pode ler/editar/apagar esse arquivo.

Execute o script como usuário normal:

$ ./teste.sh
cat: /etc/shadow: Permission denied

É o que esperávamos. Agora troque o usuário do script para root e dê permissão 4755. Lembrando que o ‘4’ serve para ativar o setuid bit.

$ su
# chown root teste.sh
# chmod 4755 teste.sh
# exit
$ ./teste.sh
cat: /etc/shadow: Permission denied

Teoricamente era para ter funcionado. Se test.sh não fosse um shell script mas um programa em C por exemplo, o conteúdo de /etc/shadow seria mostrado na tela. Isso nos leva ao próximo tópico.

Programa Setuid Que Executa Um Script

A solução é simples. Como o setuid bit é desativado em scripts então a maneira mais inteligente é criar um programa em C com esse bit ativado que execute nosso script. Quando esse programa em C for executado, TODOS os comandos do script serão executados como root.

Veja o programa abaixo:

#include
int main() {
setuid(0) ;
system("./teste.sh") ;
}

Salve como: testc.c

O programa acima simplesmente eleva seus privilégios com setuid(0) para depois executar o script. Lembre de sempre usar caminho absoluto na função system e também que o programa deve ter o setuid bit ativado, mas o script não precisa. Quando o script for executado, será criado um processo com permissão de super usuário, logo qualquer comando dele será executado como root.

Testando:

$ su
# gcc -o testc testc.c
# chmod +s testc
# exit
$ ./testc
root:c2FpIGRhcXVpIG1pbmlubwo=:15447:0:::::
bin:*:5897:0:::::
daemon:*:5897:0:::::
adm:*:5897:0:::::
lp:*:5897:0:::::
sync:*:5897:0:::::
shutdown:*:5897:0:::::
halt:*:5897:0:::::
mail:*:5897:0:::::
news:*:5897:0:::::
uucp:*:5897:0:::::
operator:*:5897:0:::::
games:*:5897:0:::::
ftp:*:5897:0:::::
smmsp:*:5897:0:::::
mysql:*:5897:0:::::
rpc:*:5897:0:::::
sshd:*:5897:0:::::
gdm:*:5897:0:::::
oprofile:*:5897:0:::::
pop:*:5897:0:::::
apache:*:5897:0:::::
messagebus:*:5897:0:::::
haldaemon:*:5897:0:::::
nobody:*:5897:0:::::
daemonio:amFoIGZhbGVpIHByYSBpciBlbWJvcmEK:15447:0:99889:7:::

Como vimos, o comando “cat /etc/shadow” foi executado como root e todo o conteúdo desse arquivo foi mostrado na tela.

Motivos Para Se Usar Esse Método

Na verdade nunca precisei de fazer isso e creio que nunca irei precisar. A regra que carrego comigo é que se um script precisa ter permissões de super usuário então ele deve ser executado pelo root. Outra alternativa também é usar o sudo para realizar tarefas de administrador com usuário comum.

Conclusão

Com certeza rodar um shell script com setuid não é muito seguro e os desenvolvedores tiveram bons motivos para desabilitar essa funcionalidade. Por isso tome cuidado em usar tal método, pois por um descuido, todo o sitema pode ser comprometido.

Então fica assim, o motivo do post foi mostrar como podemos buscar outras alternativas de realizar tarefas no linux.

Referências

[1] setuid on shell scripts by John Altenmueller (Acessado em: Agosto/2011)
http://www.tuxation.com/setuid-on-shell-scripts.html

[2] Divagação sobre Permissões, C e Linux by Daemonio (Acessado em: Agosto/2011)
https://daemoniolabs.wordpress.com/2011/03/11/divagacao-sobre-permissoes-c-e-linux-2/

3 pensamentos sobre “Setuid Em Shell Scripts

  1. Verificando a man page do system ($ man system) encontrei uma informação interessante lá em relação a isso:

    “Do not use system() from a program with set-user-ID or set-group-ID privileges, because strange values for some environment variables might be used to subvert system integrity. Use the exec(3) family of functions instead, but not execlp(3) or execvp(3). system() will not, in fact, work properly from programs with set-user-ID or set-group-ID privileges on systems on which /bin/sh is bash version 2, since bash 2 drops privileges on startup.”

    A man page reforça que usar system em programas set-user-id não é muito seguro e ela aconselha usar algumas funções da família exec.

    Para uma discussão interessante sobre o assunto, veja o link abaixo (só fui ver isso depois de ter publicado o post, hehe):

    http://stackoverflow.com/questions/1051370/why-do-i-need-setuid0-within-a-setuid-root-c-program-that-calls-an-administrati

    t+

Deixe um comentário