Usar o CmndAlias ALL
nunca será seguro
Existem 1000 maneiras de executar service network restart
sem fazer sudo service network restart
. Aqui está um exemplo do que um usuário malcriado pode tentar:
$ echo "service network restart" > /tmp/hax
$ chmod a+x /tmp/hax
$ sudo /tmp/hax
Se você fornecer aos usuários o ALL
alias de comando e tentar criar uma lista negra, eles sempre poderão encontrar uma maneira de contorná-la. Blacklist bash, e eles usarão python. Lista negra de python e eles usarão o Perl. Blacklist Perl, e eles usarão PHP. Ninguém quer isso!
Se você realmente não quer que alguém faça alguma coisa, você deve fazer como Thomas diz, e criar uma lista branca de coisas que eles estão autorizados a fazer.
Configurando uma lista branca com uma exceção
Um exemplo de uma pequena lista branca com uma exclusão pode ser encontrada na parte inferior de man sudoers
:
pete HPPA = /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd root
The user pete is allowed to change anyone's password except for root on the HPPA
machines. Note that this assumes passwd(1) does not take multiple user names
on the command line.
(De fato, este exemplo da página de manual não é seguro e pode ser explorado para alterar a senha do root! Veja os comentários abaixo para saber como.)
Podemos tentar adaptar isso ao seu caso, para oferecer todos os service
comandos ao grupo de funcionários, mas excluir os service network
comandos que lhe dizem respeito:
%staff ALL = /usr/sbin/service *, \
! /usr/sbin/service *network*, \
! /usr/sbin/service *NetworkManager*
(O ALL
nessa posição refere-se ao Host_Alias, não ao Cmnd_Alias - confuso, não é?)
O usuário não poderá executar sudo bash
ou sudo tee
ou sudo wget
ou sudo /path/to/malicious_script
. Você pode colocar na lista branca mais comandos de administração para seus usuários, se você for cuidadoso. Seja específico!
Nota: eu adicionei a *
palavra network
anterior antes, caso uma bandeira inofensiva seja adicionada à service
ferramenta no futuro. Vamos imaginar que um --verbose
sinalizador foi adicionado no futuro, então os usuários poderão executar o seguinte:
$ sudo service --verbose network restart
Portanto, precisamos *
consumir qualquer sinalizador antes do nome do serviço. A única desvantagem é que isso pode bloquear outros serviços dos quais você não se importa de executar, por exemplo, um serviço chamado safe-network
ou network-monitor
que também seria rejeitado.
Permitir que os usuários editem um arquivo usando permissões de grupo
Abaixo, você pode encontrar várias tentativas utilizando rnano
meio sudo
para permitir aos usuários editar um arquivo ou arquivos. Mas, na verdade, eles são mais complexos e mais perigosos do que deveriam ser.
Uma solução muito mais simples e segura é alterar as permissões de grupo nos arquivos específicos para os quais você deseja abrir os direitos de edição. Aqui estão alguns exemplos:
### Give steve the ability to edit his nginx config:
$ chgrp steve /etc/nginx/sites-available/steves_dodgy_project
$ chmod g+rw /etc/nginx/sites-available/steves_dodgy_project
### Let all members of the staff group edit the group_website config:
$ chgrp staff /etc/nginx/sites-available/group_website
$ chmod g+rw /etc/nginx/sites-available/group_website
Se você precisar de um controle mais refinado (por exemplo: acesso para apenas 3 usuários, mas não todos os membros da equipe), poderá criar um novo grupo usando o addgroup
comando e adicionar apenas alguns usuários.
Permita que os usuários editem um arquivo através de sudo
O restante desta resposta tornou-se uma investigação sobre como é fácil deixar buracos na sua sudo
configuração ao tentar oferecer flexibilidade aos seus usuários. Eu não recomendaria fazer o seguinte!
Se você deseja conceder aos usuários acesso para editar um arquivo específico, tente usar rnano
:
%staff ALL = /bin/rnano /etc/nginx/sites-available/host
rnano
só permitirá que eles editem o arquivo especificado. Isso é importante para impedir que um usuário mal-intencionado edite um serviço diferente (por exemplo /etc/init.d/urandom
) e adicione uma linha a ele que seria executada service network restart
.
Infelizmente, não encontrei uma maneira de restringir o rvim
suficiente (o usuário ainda pode abrir qualquer arquivo usando :e
), por isso estamos presos nano
.
Infelizmente, permitir que os usuários editem vários arquivos é muito mais difícil ...
Permita que os usuários editem vários arquivos (muito mais difícil do que deveria ser)
1. Abordagens inseguras
Cuidado com curingas! Se você oferecer muita flexibilidade (ou qualquer flexibilidade), ela poderá ser explorada:
%staff ALL = /bin/rnano /etc/nginx/sites-available/* # UNSAFE!
Nesse caso, um usuário mal-intencionado poderá editar qualquer outro script de serviço inicial e executá-lo:
$ sudo rnano /etc/nginx/sites-available/../../../any/file/on/the/system
(Na verdade, o Sudo impede .
e ..
amplia o comando, mas infelizmente não os argumentos.)
Eu esperava que algo assim pudesse funcionar, mas ainda é inseguro:
%staff ALL = /bin/rnano /etc/nginx/sites-available/[A-Za-z0-9_-]* # UNSAFE!
Como sudo
atualmente oferece apenas padrões glob , isso *
corresponderá a qualquer coisa - não é uma expressão regular!
(Edit: Eu considerei se você poderia se dar bem com o acima exposto na sua situação, porque não há subpastas abaixo sites-available
. Exigimos que um caracter seja correspondido após a pasta e /..
deve falhar após um nome de arquivo. No entanto, este não é um solução viável, porque rnano
aceita vários argumentos. E, de qualquer maneira, isso ainda seria inseguro em uma pasta que tinha subpastas!)
Mesmo se não tivermos subpastas e excluirmos quaisquer linhas que contenham /../
, a regra que oferece uma *
glob ainda poderá ser explorada, porque rnano
aceita vários argumentos (alternando entre eles <C-X>
e o espaço é aceito com prazer pela *
glob.
$ rnano /etc/nginx/sites-available/legal_file /then/any/file/on/the/system
2. Empurrar o envelope (também inseguro)
E se rejeitarmos qualquer linha que contenha espaços ou tentarmos alcançá-lo /..
? Em seguida, uma solução final viável pode ser a seguinte:
# I tried hard to make this safe, but in the end I failed again.
# Please don't use this unless you are really smart or really stupid.
%staff ALL = /bin/rnano /etc/nginx/sites-available/*, \
! /bin/rnano */..*, \
! /bin/rnano /etc/nginx/sites-available/, \
! /bin/rnano */., \
! /bin/rnano * *
# CONCLUSION: It is still NOT SAFE if there are any subfolders, due to
# the bug in rnano described below.
Aceitamos qualquer coisa "embaixo" da pasta, mas também rejeitamos qualquer chamada para rnano
se /..
ou /.
ou
somos passadas, ou se a pasta é direcionada diretamente. (Tecnicamente, a /.
exclusão torna a /..
exclusão redundante, mas deixei os dois por uma questão de clareza.)
Encontrei a pasta e as /.
exclusões eram necessárias porque, caso contrário, o usuário poderia segmentar a própria pasta. Agora você pode pensar rnano
em bloquear se apontado para uma pasta, mas você estaria errado. Na verdade, minha versão (2.2.6-1ubuntu1) inicia com um aviso moderado e um arquivo vazio; depois, <C-X>
solicita que eu insira qualquer nome de arquivo que eu gostaria de salvar, abrindo um novo vetor de ataque! Bem, pelo menos, se recusou a substituir um arquivo existente (no teste que eu fiz). De qualquer forma, como não há como colocar as subpastas na lista negra com o sudo, devemos concluir que essa abordagem é novamente insegura. Desculpe usuários!
Essa descoberta me fez duvidar da minuciosidade do nano
modo "restrito" de. Eles dizem que uma corrente é tão forte quanto seu elo mais fraco. Estou começando a sentir a combinação da sudo
magia negra da lista negra e rnano
pode não ser mais seguro do que uma cadeia de margaridas.
3. Abordagens seguras, mas limitadas
Os globos são muito restritos - eles não nos permitem combinar uma classe de personagem várias vezes. Você pode oferecer várias edições de arquivo, se todos os seus nomes de arquivos tiverem o mesmo tamanho (nesse caso, host
seguido por um único dígito):
%staff ALL = /bin/rnano /etc/nginx/sites-available/host[0-9] # SAFE
Mas se você deseja conceder ao usuário acesso para editar vários arquivos, pode ser necessário especificar explicitamente cada arquivo:
%staff ALL = /bin/rnano /etc/nginx/sites-available/hothost \
/bin/rnano /etc/nginx/sites-available/coldhost \ # SAFE
/bin/rnano /etc/nginx/sites-available/wethost \
/bin/rnano /etc/nginx/sites-available/steves_dodgy_project
Não fique tentado a usar um*
a qualquer momento. Consulte as seções 1. e 2. acima para saber o porquê! Lembre-se: um pequeno deslize pode comprometer toda a conta do superusuário e todo o sistema.
4. Escreva seu próprio verificador de argumentos (a segurança agora é de sua responsabilidade)
Espero que eles adicionem suporte a regexp sudo
no futuro; poderia resolver muitos problemas se usado corretamente. Mas também podemos precisar da capacidade de verificar as propriedades dos argumentos (para permitir apenas arquivos, apenas pastas ou apenas determinados sinalizadores).
Mas há uma alternativa para criar flexibilidade no sudo. Passar a bola:
%staff ALL = /root/bin/staffedit *
Em seguida, escreva seu próprio staffedit
script ou executável para verificar se os argumentos transmitidos pelo usuário são legais e somente execute a solicitação se forem.
networking
enetwork-manager
? Além disso, por que seus usuários têmsudo
acesso? Eles não devem, a menos que você queira que eles tenham privilégios de root completo.