Um aplicativo enorme precisa, em um momento específico, executar um pequeno número de gravações em um arquivo que requer permissões de root. Na verdade, não é um arquivo, mas uma interface de hardware que é exposta ao Linux como um arquivo.
Para evitar conceder privilégios de root a todo o aplicativo, escrevi um script bash que executa as tarefas críticas. Por exemplo, o seguinte script ativará a porta 17 da interface de hardware como saída:
echo "17" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio17/direction
No entanto, como suid
está desativado para scripts bash no meu sistema, pergunto-me qual é a melhor maneira de conseguir isso.
Use algumas soluções alternativas apresentadas aqui
Chame o script com a
sudo
partir do aplicativo principal e edite a lista de sudoers de acordo, para evitar exigir uma senha ao chamar o script. Estou um pouco desconfortável para dar privilégios ao sudoecho
.Basta escrever um programa em C, com
fprintf
e defina-o como suid root. Codifique as strings e os nomes de arquivos e verifique se apenas o root pode editá-los. Ou leia as strings de um arquivo de texto, da mesma forma, garantindo que ninguém possa editar o arquivo.Alguma outra solução que não me ocorreu e é mais segura ou mais simples que as apresentadas acima?
fonte
Respostas:
Você não precisa dar
sudo
acesso aecho
. De fato, isso é inútil porque, por exemplo, comsudo echo foo > bar
o redirecionamento é feito como o usuário original, não como root.Chame o script pequeno com
sudo
, permitindoNOPASSWD:
acesso APENAS a esse script (e a qualquer outro script semelhante) pelo (s) usuário (s) que precisam acessar.Essa é sempre a melhor / mais segura maneira de usar
sudo
. Isole o pequeno número de comandos que precisam de privilégios de root em seus próprios scripts separados e permita que o usuário não confiável ou parcialmente confiável execute apenas esse script como raiz.O
sudo
(s) script (s) pequeno (s) de tabela não deve receber args (ou entrada) do usuário (ou seja, qualquer outro programa que ele chama deve ter opções e códigos codificados) ou deve ser muito cuidadoso para validar todos os argumentos / entradas necessários. aceite do usuário.Seja paranóico na validação - em vez de procurar coisas "ruins" conhecidas a serem excluídas, permita apenas coisas "boas conhecidas" e aborte por qualquer incompatibilidade ou erro ou qualquer coisa remotamente suspeita.
A validação deve ocorrer o mais cedo possível no script (de preferência antes de fazer qualquer outra coisa como raiz).
Eu realmente deveria ter mencionado isso quando escrevi esta resposta, mas se o seu script for um shell, DEVE citar corretamente todas as variáveis. Seja especialmente cuidadoso ao citar variáveis que contenham a entrada fornecida pelo usuário de qualquer forma, mas não assuma que algumas variáveis são seguras, QUOTE ALL ALL .
Isso inclui variáveis de ambiente potencialmente controladas pelo usuário (por exemplo
"$PATH"
,"$HOME"
,"$USER"
etc. E, definitivamente, incluindo"$QUERY_STRING"
e"HTTP_USER_AGENT"
etc em um script CGI). De fato, apenas cite-os todos. Se você precisar construir uma linha de comando com vários argumentos, use uma matriz para criar a lista de argumentos e cite que -"${myarray[@]}"
.Eu já disse "citá-los todos" com bastante frequência? lembre se. faça.
fonte
Verifique o proprietário nos arquivos gpio:
Provavelmente, você descobrirá que eles pertencem ao grupo
gpio
:Nesse caso, você pode simplesmente adicionar seu usuário ao
gpio
grupo para conceder acesso sem o sudo:Você precisará se desconectar e fazer login novamente para que a alteração entre em vigor.
fonte
/sys/class/gpio/
é o gpio, mas mesmo depois de me adicionar a esse grupo, ainda recebo a "permissão negada" sempre que tento escrever alguma coisa lá./sys/class/gpio/
são na verdade apenas links simbólicos para/sys/devices/platform/soc/<some temporary name>/gpio
onde o proprietário e o grupo são raiz.chgrp gpio /sys/devices/platform/soc/*/gpio
? Talvez algo assim possa ser colocado em um arquivo de inicialização.chgrp gpio `readlink -f /sys/class/gpio/gpio18`/*
Uma solução para isso (usada principalmente na área de trabalho Linux, mas também aplicável em outros casos) é usar o D-Bus para ativar um pequeno serviço em execução como root e polkit para fazer a autorização. É basicamente para isso que o polkit foi projetado ; da documentação introdutória :
Em vez de executar seu programa auxiliar, o programa grande e sem privilégios enviava uma solicitação no barramento. Seu ajudante pode estar em execução como um daemon iniciado na inicialização do sistema ou, melhor, ser ativado conforme necessário pelo systemd . Em seguida, esse auxiliar usaria o polkit para verificar se a solicitação é proveniente de um local autorizado. (Ou, nesse caso, se isso parecer exagero, você poderá usar outro mecanismo de autenticação / autorização codificado).
Encontrei um bom artigo básico sobre comunicação via D-Bus e, embora não o tenha testado, este parece ser um exemplo básico de adição de polkit à mistura .
Nesta abordagem, nada precisa ser marcado como setuid.
fonte
Uma maneira de fazer isso é criar um programa raiz setuid escrito em C que faça apenas o necessário e nada mais. No seu caso, ele não precisa olhar para nenhuma entrada do usuário.
Não há como subverter isso através de variáveis de ambiente ou qualquer coisa, porque tudo o que faz é fazer algumas chamadas de sistema.
Desvantagem: você deve verificar o valor de retorno de cada chamada do sistema.
De cabeça: a verificação de erros é realmente fácil: se houver algum erro, apenas
perror
e salve: saia com um status diferente de zero. Se houver um erro, investigue comstrace
. Você não precisa deste programa para fornecer mensagens de erro muito boas.fonte
sudo
para que ele próprio não precise ser configurado. Aliás, é<fcntl.h>
paraopen()
.Abençoar tee em vez de eco para sudo é uma maneira comum de abordar uma situação em que você precisa limitar as permissões de raiz. O redirecionamento para / dev / null é para interromper o vazamento de qualquer saída - o tee faz o que você deseja.
fonte
tee
a execuçãosudo
, está permitindo que QUALQUER arquivo seja substituído ou anexado a (incluindo, por exemplo,/etc/passwd
- basta acrescentar uma nova conta uid = 0). Você pode também permitir que todos os comandos para ser executado comsudo
(BTW/etc/sudoers
pertence ao conjunto de 'quaisquer arquivos' assim que pode ser substituído comsudo tee
)tee
pode gravar, conforme descrito nesta resposta em uma pergunta separada. Certifique-se de ler os comentários também, pois algumas pessoas tiveram problemas com a sintaxe original usada e sugerem correções para esse problema.tee
ou operar com muitos arquivossudo
.Você pode criar um script que execute sua tarefa desejada. Em seguida, crie uma nova conta de usuário que possa efetuar login apenas fornecendo uma chave usada pelo OpenSSH.
Nota: Qualquer pessoa poderá executar esse script se tiver o arquivo de chave, portanto, certifique-se de que o arquivo de chave OpenSSH não seja legível por alguém que você deseja impedir de executar a tarefa.
Na configuração do OpenSSH (no arquivo allowed_keys), antes de especificar a chave, especifique um comando (seguido por um espaço), conforme descrito neste texto "exemplo":
command="myscript" keydata optionalComment
Esta opção de configuração pode restringir essa chave OpenSSH para executar apenas um comando específico. Agora você tem o sudo concedendo as permissões, mas a configuração do OpenSSH é a parte da solução que realmente está sendo usada para restringir / limitar o que esse usuário é capaz de fazer, para que o usuário não esteja executando outros comandos. Isso também não tem um arquivo de configuração "sudo" tão complicado, portanto, se você usa o OpenBSD ou se os novos "doas" do OpenBSD ("faça como") começam a se tornar mais populares (com versões futuras de qualquer sistema operacional usado) , você não precisará ser desafiado por muita complexidade na configuração do sudo.
fonte