Sudo: não permitir escape de shell como padrão

3

Eu não posso descobrir como desabilitar as fugas de shell para qualquer comando, para que eu possa (isto é um exemplo!) fazer algo como:

sudo-user ALL=(ALL) NOEXEC: NOPASSWD: ALL

O manual do sudoers diz isto:

A command may have zero or more tags associated with it. There are eight possible tag values, NOPASSWD, PASSWD, NOEXEC, EXEC, SETENV, NOSETENV, LOG_INPUT, NOLOG_INPUT, LOG_OUTPUT and NOLOG_OUTPUT. Once a tag is set on a Cmnd, subsequent Cmnds in the Cmnd_Spec_List, inherit the tag unless it is overridden by the opposite tag (i.e.: PASSWD overrides NOPASSWD and NOEXEC overrides EXEC)

Mas isso não descreve como definir mais de um sinalizador. Usar uma vírgula não parece funcionar (trata a segunda tag como um alias)

Melhor ainda, gostaria de definir um padrão, então a linha acima seria:

defaults NOEXEC     
sudo-user ALL=(ALL) NOPASSWD: ALL

Eu sei que o sudo pode ser compilado com noexec, mas isso não é prático neste exemplo. Eu também sei que esta não é a resposta completa - é possível subverter definindo LD_PRELOAD apropriadamente, mas é um começo.

Versão do Sudo:

Sudo version 1.8.19p2
Sudoers policy plugin version 1.8.19p2
Sudoers file grammar version 45
Sudoers I/O plugin version 1.8.19p2
On RHEL 7.5
    
por Graham Nicholls 08.10.2018 / 12:59

3 respostas

17

Não faça isso.

Você está dando à sudo-user a capacidade de executar qualquer comando como qualquer usuário. Isso inclui a capacidade de modificar /etc/sudoers usando qualquer ferramenta que não exija a execução de subprocessos. Você pode estar pensando que exclui visudo , mas estritamente falando, você não precisa visudo para editar /etc/sudoers .

Como, por exemplo:

sudo-user$ sudo sed --in-place -e '/^sudo-user/s/NOEXEC://' /etc/sudoers

... e o usuário acabou de remover a restrição NOEXEC: .

Uma restrição que o usuário pode remover à vontade não é uma restrição verdadeira.

Além disso, NOEXEC: pode causar problemas. Ele não apenas evita escapes do shell: ele impede que o programa seja executado com sudo de iniciando diretamente quaisquer outros programas . Isso pode ter muitas conseqüências.

Por exemplo, se o seu sudo-user parar e depois reiniciar o daemon cron (por exemplo, para interromper as tarefas agendadas enquanto durar alguma manutenção), o daemoncron reiniciado não poderá realmente executar nenhuma tarefa agendada porque da restrição NOEXEC: .

NOEXEC: existe para que o administrador do sistema possa aplicá-lo a programas cuidadosamente selecionados que podem executar sua tarefa sem exec() de quaisquer subprocessos. Aplicá-lo cegamente a tudo causará problemas.

Mas se você absolutamente precisa, aqui está como.

Na página sudoers(5) man:

User specification
 User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \
               (':' Host_List '=' Cmnd_Spec_List)*

 Cmnd_Spec_List ::= Cmnd_Spec |
                    Cmnd_Spec ',' Cmnd_Spec_List

 Cmnd_Spec ::= Runas_Spec? SELinux_Spec? Tag_Spec* Cmnd

 Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')'

 SELinux_Spec ::= ('ROLE=role' | 'TYPE=type')

 Tag_Spec ::= ('EXEC:' | 'NOEXEC:' | 'FOLLOW:' | 'NOFOLLOW' |
               'LOG_INPUT:' | 'NOLOG_INPUT:' | 'LOG_OUTPUT:' |
               'NOLOG_OUTPUT:' | 'MAIL:' | 'NOMAIL:' | 'PASSWD:' |
               'NOPASSWD:' | 'SETENV:' | 'NOSETENV:')

Esta é uma descrição detalhada de como construir uma linha especificação do usuário para o arquivo sudoers . Pode ser um pouco entediante ler, mas contém as informações de que você precisa.

Vamos resolver isso usando sua linha de exemplo:

sudo-user ALL=(ALL) NOEXEC: NOPASSWD: ALL

A linha inteira é conhecida como especificação do usuário , ou User_Spec .

Ele é dividido da seguinte forma:

  • User_List tem apenas um usuário no seu exemplo: sudo-user
  • Host_List tem apenas uma entrada, ALL
  • Cmnd_Spec_List no seu exemplo é (ALL) NOEXEC: NOPASSWD: ALL
  • não há mais : Host_List = Cmnd_Spec_List unidades nessa linha (o asterisco após parênteses sugere que pode haver zero ou mais unidades adicionais como essa).

Seu Cmnd_Spec_List não tem vírgulas, por isso tem apenas um Cmnd_Spec .

Cmnd_Spec se divide em:

  • opcional Runas_Spec : no seu caso, (ALL)
  • opcional SELinux_Spec , que não existe no seu exemplo
  • zero ou mais Tag_Spec s, que é a parte sobre a qual você deseja saber
  • Cmnd , o comando, que é ALL no seu caso.

E um único Tag_Spec é apenas uma das palavras-chave listadas com dois pontos no final, sem vírgula, espaço ou outro delimitador listado explicitamente. A linha Cmnd_Spec ::= nos diz exatamente onde colocar espaços nessa linha. Como não há instruções para colocar espaços ou quaisquer outros delimitadores entre as tags, não faça isso.

Então, basta colocar as tags uma após a outra , assim:

sudo-user ALL=(ALL) NOEXEC:NOPASSWD: ALL
    
por 08.10.2018 / 14:24
5

Você não precisa de uma tag para isso, pois noexec também é um sinalizador booleano para a linha de entrada Padrão:

noexec

If set, all commands run via sudo will behave as if the NOEXEC tag has been set, unless overridden by a EXEC tag. See the description of NOEXEC and EXEC below as well as the Preventing shell escapes section at the end of this manual. This flag is off by default.

Então tudo que você precisa é

Defaults        noexec

Isso terá os mesmos problemas que a telcoM observa na sua resposta . Isso impedirá que visudo seja executado (já que isso precisa iniciar um processo de editor separado), portanto, será mais difícil desfazer a alteração posteriormente.

    
por 08.10.2018 / 14:44
0

Combinando as duas respostas dadas até agora, que tal isso:

Defaults noexec
root    ALL=(ALL)       ALL
%wheel  ALL=(ALL)       ALL
sudo-user ALL=(ALL)     EXEC:NOPASSWD:  ALL
fred ALL=(ALL)          NOPASSWD:  user_allowed_commands

Na verdade, eu estou propondo dar acesso irrestrito ao sudo-user. Este parece ser o método recomendado (no Ubuntu et al, pelo menos), ao invés de usar root. Eu já estou auditando o diretório / etc / sudoers quando isso acontece. Isso permite que o fred execute a lista de comandos em "user_allowed_commands" (assumindo que fork / exec não é necessário, o que parece improvável, TBH - ou estou interpretando mal o que o noexec está fazendo?)

Eu gostaria de adicionar isso do @telcoM: Uma restrição que o usuário pode remover à vontade não é uma restrição real.

Em todas as implementações do SELinux que vejo, não é imutável, então qualquer usuário pode executar o setenforce permissivo, e todas as restrições são removidas.

    
por 08.10.2018 / 15:47

Tags