Como impedir que usuários do sudo executem comandos específicos?

29

Eu tenho uma configuração de rede muito sensível e eu realmente não quero estragar tudo. Minha rede consiste em vários usuários com privilégios de sudo.

Eu quero impedi-los de correr

service NetworkManager restart
service network restart

comandos.

Existe alguma maneira de conseguir isso?

shekhar
fonte
Qual distribuição você está usando? Os nomes dos serviços são específicos da distribuição e eu não conheço nenhuma distribuição que use os nomes que você possui lá. Você quer dizer networkinge network-manager? Além disso, por que seus usuários têm sudoacesso? Eles não devem, a menos que você queira que eles tenham privilégios de root completo.
terdon
@terdon eu resolvi isso. Obrigado. Eu não posso postá-lo como resposta, porque eu sou um novo usuário
Shekhar
Sim, você pode, por favor. Eu também gostaria de saber a resposta que você encontrou.
terdon
@terdon certeza, mas a sua dizendo que eu preciso esperar para 8 horas para postar minha própria resposta, porque eu não tenho mesmo 10 reputação
shekhar
1
Ah, sim, desculpe, você realmente precisa esperar. Eu só upvoted, você tem a rep agora :)
terdon

Respostas:

47

Usar o CmndAlias ALLnunca será seguro

Existem 1000 maneiras de executar service network restartsem 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 ALLalias 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 servicecomandos ao grupo de funcionários, mas excluir os service networkcomandos que lhe dizem respeito:

%staff ALL =   /usr/sbin/service *,                            \
             ! /usr/sbin/service *network*,                    \
             ! /usr/sbin/service *NetworkManager*

(O ALLnessa posição refere-se ao Host_Alias, não ao Cmnd_Alias ​​- confuso, não é?)

O usuário não poderá executar sudo bashou sudo teeou sudo wgetou 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 networkanterior antes, caso uma bandeira inofensiva seja adicionada à serviceferramenta no futuro. Vamos imaginar que um --verbosesinalizador 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-networkou network-monitorque 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 rnanomeio sudopara 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 addgroupcomando 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 sudoconfiguraçã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

rnanosó 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 rvimsuficiente (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 sudoatualmente 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 rnanoaceita 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 rnanoaceita 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 rnanose /..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 rnanoem 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 nanomodo "restrito" de. Eles dizem que uma corrente é tão forte quanto seu elo mais fraco. Estou começando a sentir a combinação da sudomagia negra da lista negra e rnanopode 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, hostseguido 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 sudono 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 staffeditscript ou executável para verificar se os argumentos transmitidos pelo usuário são legais e somente execute a solicitação se forem.

joeytwiddle
fonte
5
Essa resposta levou muito tempo, mas finalmente acho que entendo como o sudo funciona. Desisti em várias ocasiões no passado, achando ALL=(ALL:ALL) ALLmuito semântica, mas sempre presumi que em algum lugar haveria um verificador decente de argumentos ... Eu estava errado. É realmente muito limitado. Até a exclusão de raiz de senha oferecida na página de manual pode ser quebrada com um simples argumento de linha de comando sudo passwd -q root,. Bem, os autores do sudo listam [algumas alternativas] (sudo.ws/sudo/other.html) em seu site. Espero que eles adicionem suporte a regexp no futuro.
joeytwiddle
Você usa especificamente rnanosua descrição aqui porque é uma versão do nano que não possui a função 'salvar como'? Não estou familiarizado com o programa.
Shadur 30/03/14
Sim. Se nos preocupamos com a segurança, o editor deve editar apenas o arquivo especificado e não deve abrir um shell. Para informações, $ man nanoentão/-R<Enter>
joeytwiddle
Correção: Para quebrar o exemplo pete, o -qdeve vir depois: sudo passwd root -q. O exemplo pete pode ser reforçado excluindo *root*.
Joeytwiddle 17/02
Considere usar sudoeditpara habilitar com segurança a modificação de arquivos com sudo.
Totor
5

Primeiro, abra o arquivo sudoers com sudo visudo. A adição de user ALL=!/usr/sbin/serviceIIRC não permitirá o servicecomando para o usuário user.

Fontes: http://nixcraft.com/showthread.php/15132-Sudo-Exclude-Commands-and-Disable-sudo-su-Bash-Shell

Zeb McCorkle
fonte
Isso irá parar de executar outros serviços também e eu não quero isso. Obrigado pela resposta. :)
shekhar
enquanto sua resposta não me ajudou exatamente, mas ajudou a encontrar uma solução, obrigado. mas você sabe que para lhe dar um voto positivo ou postar minha resposta de trabalho, não tenho reputação suficiente. Certamente vou agradecer assim que for. Obrigado.
shekhar
2
Sim, mas ainda assim, como outros declararam, você precisa ter muito cuidado com isso. Existem várias maneiras de obter acesso. Qualquer comando que possa gerar um shell e assim por diante. É muito mais fácil descobrir quais comandos eles realmente precisam e permitir que eles, em vez de tentar excluir todos os "proibidos".
Bonsi Scott
3
As listas de permissões não são mantidas em muitos cenários. O objetivo real pode não ser impedi- los de fazer algo, mas impedi-los de fazer algo ruim por engano, sem restringi-los. Listas negras são boas nesses casos. Você lista negra as maneiras pelas quais um usuário razoável executaria a tarefa. Mas a lista negra via sudo pode não ser suficiente - as pessoas podem e usam 'sudo bash'. Uma abordagem seria quebrar o comando 'service' e, nos casos em que você não deseja que eles usem, informe-os. Mas você nunca listará todas as boas ações em uma lista de permissões, nem todas as más em uma lista negra.
Bob Kerns 30/03
1
Eu concordo com você Bob. Para permitir flexibilidade, sem permitir acesso total, muitas vezes você precisará rolar sua própria solução, como um script auxiliar, e colocar na lista de permissões somente esse script. as listas de permissões sudo podem fazer o que você precisa, mas geralmente elas são muito limitadas ou fáceis de explorar.
joeytwiddle
5

Eu encontrei a solução.

Abri o terminal e mudei para usuário root su -e digitei visudopara editar.

então, no final, escrevi linhas como

user ALL=!/etc/init.d/NetworkManager restart
user ALL=!/etc/init.d/network restart

Então eu salvei e fechei e reiniciei também.

Agora, se eu estou digitando como service network restartou service NetworkManager restartnão está me permitindo e está dando um erro como

Sorry user is not allowed to execute '/sbin/service NetowkrManager restart' as root on localhost.localdomain

e da mesma forma para o service network restartcomando também.

shekhar
fonte
12
Isso funcionará para usuários inexperientes e mal-intencionados, mas é fácil contornar as restrições do sudo (por exemplo, sudo cp -p /etc/init.d/network /etc/init.d/network-not-in-sudoe depois sudo /etc/init.d/network-not-in-sudo restart). É por isso que é muito mais seguro criar inclusões em vez de exclusões no arquivo sudoers, por exemplo, indicar com quais serviços eles têm permissão para interagir.
Thomas
Tudo o que a 'reinicialização da rede de serviço' faz, você pode fazer com outros comandos, como os do script init.d da rede. Eu nem vou tentar listá-los aqui. Mas se você deseja, por exemplo, impedir realmente modificações no estado da interface, uma política do SELinux me parece ser o caminho a seguir. É um tópico complexo, mas quando uma lista de permissões é muito restritiva ou onerosa e uma lista negra é inadequada, provavelmente é a melhor opção. Ele é implementado no kernel e permite restringir o acesso às interfaces de rede (e outros recursos), mesmo aos usuários sudo'd.
Bob Kerns
Se for possível com o SELinux, então ficaria mais satisfeito. @BobKerns Obrigado. Vou tentar dessa maneira.
shekhar
3

A resposta real para isso é que você realmente não pode impedir isso. Você pode impedir que alguém não intencional execute acidentalmente esse comando por meio dos métodos descritos nas outras respostas, mas se alguém realmente deseja executá-lo e está na lista de sudoers, ele pode executá-lo. Por exemplo, eles poderiam fazer o seguinte:

joe@box:~$ sudo bash root@box:~# service network restart

Ou outro comando divertido que eles poderiam usar para contornar suas restrições no arquivo sudoers:

sudo visudo

Para encurtar a história, se você pode sudo e não se restringe à execução de comandos específicos, pode fazer praticamente o que quiser. Mesmo que você os restrinja a um determinado conjunto de comandos, você deverá certificar-se de que não é possível ao usuário copiar outro comando que ele queira executar com o mesmo nome de um que ele tenha permissão para executar ( como sobrescrevendo o comando que eles têm permissão para executar.)

reirab
fonte
Sim. Deve-se evitar comandos que possam gerar um shell a partir de dentro.
Bonsi Scott
1
O problema é que não são os comandos que você deseja proteger, mas o estado dos objetos do kernel, como tabelas de roteamento, interfaces etc. - não importa qual comando (ou chamada de sistema) seja usado. E você deseja protegê-lo de alguns, mas não de todos, usuários root. O SELinux foi projetado para esse tipo de cenário. Mas primeiro, eu começaria com uma revisão do porquê todos esses usuários têm acesso ao sudo. Se eles precisarem fazer apenas algumas coisas específicas, as operações da lista de permissões em sudoers podem ser tudo o que você precisa.
precisa
2

Use firejail para restringir usuários com caixas de areia.

https://github.com/netblue30/firejail/

Defina firejail como shell em vez de bash em / etc / passwd, para todos os usuários que você deseja restringir. É muito fácil de usar e possui uma boa documentação.

Exemplo:

user:x:1000:1000:user:/home/user:/usr/bin/firejail
Jeff
fonte