Missão

Desenvolvermos soluções acessíveis e de qualidade, solucionando os problemas e agregando valor ao serviço prestado por nossos clientes.

Visão

Sermos reconhecidos como profissionais de excelência em nossas áreas de atuação.

Compromisso

Fornecer aos clientes o melhor serviço e com a melhor qualidade.

Uso de scripts SUID em Perl

Motivação

Há uns tempos atrás, mais ou menos uns 2 ou 3 meses (agosto ou setembro de 2002) tive problemas com a utilização de scripts Perl com o SUID bit ativado.

Minha primeira tentativa foi corrigir as permissões de todos os binários utilizados pelo próprio Perl, pensando que o problema poderia ter sido causado por uma atualização realizada um ou dois dias antes.

Minhas tentativas foram em vão, e então recorri a um grupo de usuários de Perl. Uma das respostas informava-me para recompilar o Perl. Após pensar um pouco, decidi fazê-lo e isto realmente resolveu o problema (minha distribuição de Linux havia desativado esta opção).

O interessante é que uma outra resposta, ao meu post informando que isso tinha resolvido o problema, dizia que eu não deveria usar os binários do Perl para scripts SUID. Devido ao remetente (Randal Schwartz — ou "merlyn", como é conhecido), questionei alguns motivos e as explicações de que era muito fácil explorar alguma vulnerabilidade no sistema foram mais do que suficientes para me convencer a seguir seus conselhos.

Com base nisto, decidi escrever este pequeno tutorial explicando como proceder para, de forma segura, utilizar scripts com o SUID ou SGID (ou ambos!) bit ativado.

Pré-requisitos

Código C

#define REAL_PATH "/path/to/script"
main(ac, av) 
char **av; 
{
 execv(REAL_PATH, av);
}

Código Perl para testes

#!/usr/bin/perl -w
#
# Este script está gravado com o seguinte nome: /home/godoy/teste.pl

use English;
print $EUID, "\n";

O módulo English é usado apenas para evitar o uso de $> no lugar de $EUID. Se não o tiver instalado, efetue a substituição inversa (recomendo ter este módulo; seus programas serão muito mais legíveis e fáceis de manter).

O resultado deste script é, em minha máquina:

[godoy@wintermute ~]$ perl teste.pl
550
[godoy@wintermute ~]$ id godoy
uid=550(godoy) gid=550(godoy) grupos=550(godoy),24(cdrom),29(audio),400(desenv),907(ldp),551(cvs)
[godoy@wintermute ~]$ 

Em sua máquina o número do usuário pode ser outro.

Código utilizado

O código C acima é genérico e pode ser modificado rapidamente para a execução de qualquer script. A única exigência é que o script em questão possua o bit de execução ativado ou se defina REAL_PATH de modo a invocar o interpretador perl.

O código C utilizado foi, então, o seguinte:

#define REAL_PATH "/home/godoy/teste.pl"
main(ac, av) 
        char **av; 
{
         execv(REAL_PATH, av);
}

Testes e resultados

Um primeiro teste deve ser realizado para que possamos verificar o resultado da execução do programa em C sem nenhuma condição especial, exceto que o usuário que seja seu proprietário (owner) seja o superusuário.

[godoy@wintermute ~]$ ls -l wrapper_teste
-rwxrwxr-x    1 godoy    godoy        4796 Nov  6 19:04 wrapper_teste
[godoy@wintermute ~]$ sudo chown root wrapper_teste
[godoy@wintermute ~]$ ls -l wrapper_teste
-rwsrwsr-x    1 root     godoy        4796 Nov  6 19:04 wrapper_teste
[godoy@wintermute ~]$ ./wrapper_teste 
550
[godoy@wintermute ~]$ 

O resultado foi o esperado, ou seja, nenhuma referência ao usuário root como o responsável pela execução do processo.

O próximo passo consiste em ativar o SUID bit no script:

[godoy@wintermute ~]$ sudo chmod +s wrapper_teste
[godoy@wintermute ~]$ ls -l wrapper_teste
-rwsrwsr-x    1 root     godoy        4796 Nov  6 19:04 wrapper_teste
[godoy@wintermute ~]$ ./wrapper_teste            
0
[godoy@wintermute ~]$

O resultado, novamente, foi o esperado: o script foi executado pelo super usuário, com os acessos e restrições deste.

Considerações sobre segurança

A única coisa deve ser garantida é a segurança aos arquivos que serão executados (assim como deve ser garantida para scripts Perl que usavam os métodos do próprio Perl para obterem privilégios adicionais) já que quem os executará terá permissões de super usuário.

O fato do script ser executado como se o fosse pelo super usuário implica que se alguém substituir o script Perl, ele poderá executar qualquer coisa como se fosse o próprio root.

Mesmo com esta preocupação adicional, este método é bem mais seguro que o via suidperl.

Sobre este documento

Autor: Jorge Godoy

Data: 06 de novembro de 2002

Última atualização: 06 de novembro de 2002

“Um novo conceito em prestação de serviços”