Qual é a maneira mais segura de iniciar um processo no nível da raiz via cgi em um servidor Apache?

3

O problema: Eu tenho um script que é executado periodicamente através de um cron job como root , mas eu quero dar às pessoas uma maneira de iniciá-lo de forma assíncrona também, através de uma página web. (O script será escrito para garantir que ele não execute instâncias sobrepostas ou algo semelhante.)

Eu não preciso que os usuários façam login ou tenham uma conta, eles simplesmente clicam em um botão e, se o script estiver pronto para ser executado, ele será executado. Os usuários podem selecionar argumentos para o script (muito filtrados como entradas), mas, para simplificar, diremos que eles só têm o botão para pressionar.

Como um teste simples, criei um script Python em cgi-bin. chown-ing-lo root: root e, em seguida, aplicando "chmod ug +" para ele não tem os resultados desejados: ele ainda acha que tem o grupo efetivo da conta do servidor web ... pelo que eu posso dizer isso não é permitido.

Eu li que envolvê-lo com um programa cgi compilado faria o trabalho, então eu criei um wrapper C que chama meu script (suas permissões restauradas ao normal) e deu ao executável as permissões root e o bit setuid. Isso funcionou ... o script foi executado como se o root o tivesse executado.

Minha principal questão é, isso é normal (a necessidade do wrapper binário fazer o trabalho) e essa é a maneira segura de fazer isso? Não é voltado para o mundo, mas ainda assim, gostaria de aprender as melhores práticas.

Mais amplamente, muitas vezes me pergunto por que um binário compilado é mais "confiável" do que um script na prática? Eu acho que você confiaria em um arquivo que fosse legível por humanos ao invés de um binário críptico. Se um invasor puder editar um arquivo, você já estará com problemas, mais ainda se ele não puder ser examinado com facilidade. Em resumo, eu esperaria que fosse o contrário. Seus pensamentos?

    
por MartyMacGyver 27.10.2012 / 06:09

3 respostas

3

Primeiro de tudo: não faça isso, ou pelo menos não permita que nenhum parâmetro seja passado da web para o seu aplicativo raiz.

Agora, à sua pergunta real: quando você escreve um script (Python no seu caso), ele é executado pelo interpretador. Então, para poder rodar o script como root, você precisaria definir o suid-root do interpretador python, mas você realmente não quer fazer isso. Isso ocorre porque seu script não é um executável como tal, mas apenas um conjunto de regras para o interpretador. Quando você quebra seu script com um executável binário, agora você tem novamente um executável que ganha direitos de root e o interpretador python chamado do executável também tem root. Mais informações sobre isso podem ser encontradas em Não é possível definir o UID em scripts de shell e < href="http://www.diablotin.com/librairie/networking/puis/ch05_05.htm"> link

Dito isso, chamar o script via sudo como @SvenW sugeriu deve funcionar bem.

    
por 27.10.2012 / 19:41
6

Outra resposta, já que esta é uma abordagem completamente diferente (e muito mais genérica). Alguém poderia argumentar que esta é a maneira canônica de fazer tais coisas :)

Coloque seu usuário do apache (no entanto, ele é chamado, eu assumo www-data ) no arquivo sudoers ( com visudo ) com uma linha muito específica que permite executar somente yourscript.py e somente a partir da máquina local ( hostname ), sem uma senha. Algo parecido com isto:

www-data hostname=(root)NOPASSWD:/path/to/yourscript.py

Seu script CGI pode então iniciar este script com uma chamada para sudo /path/to/yourscript.py .

É claro que você precisa ter certeza absoluta de que os parâmetros que você pode usar para este script estejam totalmente restritos aos valores permitidos - de forma ideal, tanto do script do cgi wrapper quanto do yourscript.py .

    
por 27.10.2012 / 13:41
3

A maneira mais fácil (e bastante segura) do IMHO é indireta: fazer a página criar um arquivo em algum lugar se o usuário clicar no botão e modificar seu script para ser executado somente se o arquivo existir e excluí-lo depois. Em seguida, execute este script a partir de uma tarefa cron a cada minuto. Você pode até usar esse arquivo para fornecer argumentos ao script (o que obviamente requer atenção especial).

Isso deixa espaço para melhorias (cliques simultâneos de vários usuários sendo um), mas eu usei essa abordagem para fins de limpeza e de ação única muitas vezes.

    
por 27.10.2012 / 07:01