Como sempre impor a senha sudo para um comando específico?

12

Outro dia eu estava fazendo algumas tarefas de manutenção no meu servidor web. Eu estava com pressa e com sono, então eu fiz tudo usando o comando sudo .

E então, acidentalmente pressione Ctrl + V , enviando este comando para o meu servidor web:

sudo rm -rf /*

Para aqueles que se perguntam o que o comando acima faz: Isso excluiu meu todo servidor da web

Por sorte, eu tinha backups e, infelizmente, tive que passar mais duas horas acordado para corrigir esse erro incrível. Mas desde então, tenho me perguntado:

Existe uma maneira de sempre impor a senha do sudo para um comando específico?

Se o servidor me pedisse uma senha, eu evitaria muitos problemas. Não, porque eu corri cerca de 5% de comandossudo antes deste erro majestoso.

Então, existe uma maneira de fazer isso? Eu só preciso da senha com o comando rm para ser sempre aplicado. Outros comandos que estou usando geralmente são nano ou cp , ambos são (até certo ponto) revertíveis.

    
por Pavel Janicek 11.05.2018 / 09:28

4 respostas

17

Você pode definir o timestamp_timeout para 0 para comandos específicos em /etc/sudoers . Crie um arquivo visudo -f /etc/sudoers.d/pduck com o seguinte conteúdo:

Cmnd_Alias DANGEROUS = /bin/rm

Defaults!DANGEROUS timestamp_timeout=0

pduck ALL = (ALL:ALL) DANGEROUS

Agora, o usuário pduck é sempre solicitado a fornecer uma senha ao executar sudo rm (independentemente dos parâmetros adicionais), embora o usuário seja membro do grupo sudo e sudo lembre sua senha para outros comandos.

A desvantagem é que você não pode adicionar facilmente parâmetros à linha /bin/rm no arquivo para restringir ainda mais isso. Bem ... você pode, como:

Cmnd_Alias DANGEROUS = /bin/rm -f

mas você é solicitado exatamente por sudo rm -f e não (novamente) por sudo rm -rf , por exemplo.

    
por PerlDuck 11.05.2018 / 13:28
9

Um método seria usar safe-rm . Isso irá APENAS endereçar o uso de "rm" e impedir que versões específicas de "rm" sejam executadas. Isso inclui a remoção do sistema de raiz, mas também pode ser usado para impedir a remoção de diretórios relacionados ao sistema, como "/ usr /" ou "/ var /". Do link:

Reventing the accidental deletion of important files

Safe-rm is a safety tool intended to prevent the accidental deletion of important files by replacing /bin/rm with a wrapper, which checks the given arguments against a configurable blacklist of files and directories that should never be removed.

Users who attempt to delete one of these protected files or directories will not be able to do so and will be shown a warning message instead:

$ rm -rf /usr   
Skipping /usr

(Protected paths can be set both at the site and user levels.)

Recovering important files you deleted by mistake can be quite hard. Protect yourself today by installing safe-rm and reduce the likelihood that you will need to contact a data recovery service!

    
por Rinzwind 11.05.2018 / 09:45
3

sudo fornece uma opção -k, --reset-timestamp , consulte man sudo :

When used in conjunction with a command or an option that may require a password, this option will cause sudo to ignore the user's cached credentials. As a result, sudo will prompt for a password (if one is required by the security policy) and will not update the user's cached credentials.

Você pode escrever um wrapper simples para sudo testing para rm -rf /* e execução

sudo -k rm -rf /*

em vez disso, por exemplo assim:

sudo ()                                                                                                                                                 
{ 
    [[ "$*" == "rm -rf /*" ]] && opt="-k";
    /usr/bin/sudo $opt "$@"
}

Exemplo de uso

Teste com echo a aqui.

$ sudo echo
[sudo] password for dessert: 

$ sudo echo

$ sudo echo a
[sudo] password for dessert: 
a
$ sudo echo a
[sudo] password for dessert: 
a

Se você quiser que seja perguntado a cada vez que você executar rm em geral, você pode adaptar a função acima da seguinte forma:

sudo () 
{ 
    [[ "$1" == "rm" ]] && opt="-k";
    /usr/bin/sudo $opt "$@"
}

Se você quiser combinar as chamadas de comando geral e as linhas de comando específicas, recomendamos usar case , por exemplo:

sudo () 
{ 
    case "$*" in 
        rm*)            opt="-k" ;;
        "mv /home"*)    opt="-k" ;;
        "ln -s /usr/bin/fish /bin/sh") opt="-k" && echo "Don't you dare!" ;;
        *)              opt="" ;;
    esac;
    /usr/bin/sudo $opt "$@"
}

Observe que essas abordagens não funcionarão se você executar sudo com opções - as soluções possíveis são [[ "$*" =~ " rm " ]] para verificar a cadeia "rm" cercada por espaços ou *" rm "*) com case para capturar qualquer linha de comando contendo "rm".

    
por dessert 11.05.2018 / 10:01
1

Esta resposta não aborda a parte sudo da sua pergunta, mas, por outro lado, trata de uma maneira de reduzir o perigo de invocações acidentais de rm para qualquer usuário

Você pode codificar rm para rm -I , o que

  • pede confirmação assim que excluiria um diretório ou mais de 3 arquivos
  • contanto que você deixe de fora -f , o que substitui as opções anteriores de -I .

--one-file-system é outra possível salvaguarda contra a eliminação não intencional que utilizo no meu rm alias.

Configuração

Para criar um alias, use o comando:

alias rm='rm -I --one-file-system'

Você pode colocá-lo em seu ~/.bashrc ou mesmo /etc/bash.bashrc .

Uso

$ sudo rm -r /etc/apt/sources.list.d /*
rm: remove all arguments?

Para confirmar o tipo yes ou sua tradução em sua localidade ou na primeira letra de uma das duas palavras e pressione Enter . Qualquer outra entrada, incluindo nenhuma, aborta a operação.

    
por David Foerster 12.05.2018 / 09:12