Um programa pode dizer que está sendo executado no sudo?

27

Eu tenho um programa que deve se comportar de maneira diferente se estiver sendo executado no "sudo". Existe uma maneira de descobrir se foi executado no sudo?

Atualização: Alguém perguntou por que eu gostaria de fazer isso. Nesse caso, em um Mac usando MacPorts, existe uma saída que solicita que você copie e cole um comando específico. Se o comando MacPorts foi executado com "sudo", ele deve incluir sudo no comando de amostra:

$ sudo port selfupdate 
--->  Updating MacPorts base sources using rsync
MacPorts base version 2.2.1 installed,
MacPorts base version 2.2.1 downloaded.
--->  Updating the ports tree
--->  MacPorts base is already the latest version

The ports tree has been updated. To upgrade your installed ports, you should run
  port upgrade outdated

^^^^^^^^^ it would be really sweet if it output "sudo port upgrade outdated" instead.  It would be even better if it just did it for you :-)
TomOnTime
fonte
Estou curioso: você pode explicar como deve se comportar de maneira diferente?
sciurus 21/01
11
@sciurus geralmente o caso de uso comum está em um script de instalação que requer privilégios de root; se você não os tiver, morra imediatamente.
Nick T
3
Isso soa como meta.stackexchange.com/questions/66377/what-is-the-xy-problem/… . O que você realmente quer fazer?
Jenny D diz Restabelecer Monica
Lembro-me vagamente algum comando estar ciente de que ele é executado como root ou não ... Eu acho que a resposta é "sim"
Rolf

Respostas:

48

Sim, existem 4 variáveis ​​de ambiente definidas quando um programa está sendo executado no sudo:

$ sudo env |grep SUDO
SUDO_COMMAND=/usr/bin/env
SUDO_USER=tal
SUDO_UID=501
SUDO_GID=20

Observe que eles podem ser falsificados simplesmente configurando-os. Não confie neles para nada crítico.

Por exemplo: Neste programa, precisamos dizer ao usuário para executar outro programa. Se o atual foi executado com sudo, o outro também será.

#!/bin/bash

echo 'Thank you for running me.'

if [[ $(id -u) == 0 ]]; then
  if [[ -z "$SUDO_COMMAND" ]]; then
    echo 'Please now run: next_command'
  else
    echo 'Please now run: sudo next_command'
  fi
else  echo 'Error: Sadly you need to run me as root.'
  exit 1
fi

Observe que ele só testa uma variável SUDO_ * se puder primeiro provar que está executando como root. Mesmo assim, ele o usa apenas para alterar algum texto útil.

TomOnTime
fonte
2
O que eu usaria para "qualquer coisa crítica?"
Kevin - Restabelece Monica
3
@ Kevin se alguém estraga seu ambiente para fingir ter privilégios elevados, então, esperançosamente, sabe o que está fazendo e aceita as consequências.
Nick T
Votado porque qualquer resposta que precise ser qualificada por "não confie neles para qualquer coisa crítica" não é uma resposta, mas um truque feio.
Stephen C
Esta é uma resposta perfeitamente aceitável para a pergunta que foi feita. O aviso precisa estar lá para pessoas que podem tentar impedir o uso do sudo, em vez de apenas detectá- lo. A prevenção deve ser feita usando os aliases de comando do sudo para limitar quais comandos o usuário pode executar.
dwurf 15/09
11

Isso não responde diretamente à pergunta, mas acho que a pergunta correta não está sendo feita aqui. Parece-me que o solicitante quer um programa que atue de forma diferente se tiver certas permissões ou não, no entanto, eu diria que verificar se o sudo não é a maneira de fazer isso. Em primeiro lugar, muitos sistemas podem não implementar um "sudo", não é de forma alguma necessário no Linux ou em muitos Unixes.

Por exemplo, um usuário já pode estar logado como root, tornando o sudo sem sentido ou talvez o sistema tenha usuários não root que ainda tenham recursos para executar a tarefa administrativa que o programa deseja executar. Finalmente, talvez o sistema não possua root ou sudo e, em vez disso, use um sistema de controle de acesso obrigatório com recursos diferentes e sem capturar todos os superusuários nos quais o sudo se encontra. Ou o usuário pode ser sudoed, mas em uma conta que tenha permissões sem a sua própria conta por motivos de segurança (eu geralmente corro código não confiável com um usuário temporário sem privilégios, que só pode gravar em ramdisks para descartar, não aumentar minhas permissões ) No geral, é uma má idéia assumir um modelo de permissões específico, como sudo ou a existência de raiz, ou assumir que um usuário sudoed possui privilégios específicos.

Se você deseja descobrir se possui permissões para executar uma operação, a melhor maneira é tentar e fazê-lo. Verifique errno quanto a problemas de permissão, se falhar ou se for uma operação em vários estágios, que deve falhar ou ter êxito. você pode verificar se uma operação funcionará com funções como a função de acesso POSIX (cuidado com as possíveis condições de corrida aqui se as permissões estiverem sendo alteradas ativamente)

Se você precisar conhecer o usuário real por trás do sudo, além disso, poderá usar a função getlogin , que deve funcionar em qualquer sessão interativa com um terminal subjacente e permitir, por exemplo, descobrir quem está 'realmente' executando o comando para auditoria ou encontrar o diretório inicial do usuário real para salvar logs.

Finalmente, se o que você realmente deseja é descobrir se um usuário tem acesso root (ainda é uma má idéia, mas menos específica de implementação), você pode usar o getuid para verificar se há um uid 0 e, portanto, root.

Validade
fonte
7

Existem dois mecanismos que podem ser usados.

  • A verificação das variáveis ​​de ambiente pode ser falsificada de qualquer maneira, mas é a mais fácil de fazer. growisofsnão gosta de rodar em SUDO, então desmarco as variáveis ​​SUDO nos scripts em que as uso. Pode ser falsificado de outra maneira. (A variável SUDO também é transportada para o ambiente para scripts executados sob os comandos at e batch.)
  • Outra maneira de verificar se você está executando o sudo é percorrer a lista de processos do processo pai, procurando o sudo. Seria difícil esconder que você estava executando o sudo dessa maneira, mas é mais complexo. Ainda é possível fingir que você está executando no sudo.

É mais comum verificar se você está executando como o usuário apropriado. O idcomando pode ser usado para fazer isso. O script do TomOnTime usa o idcomando para determinar se sudopode ser necessário executar o próximo comando.

BillThor
fonte
11
> Seria difícil esconder que você estava executando o sudo dessa maneira. Você não poderia simplesmente mudar o nome do sudobinário para outra coisa? Ou cite outro executável sudopara fingir o contrário? Não que eu realmente esperar que alguém em sã consciência fazer isso ...
Bob
@ Bob Você precisaria rootacessar para renomear o sudoexecutável. Um usuário normal não seria capaz de fazer isso. Eu notei que você pode fingir que está sendo executado sudo. Renomear um programa existente funcionaria. O código necessário para um sudoprograma falso dedicado é trivial.
BillThor
você pode apenas baixar o binário sudo de algum lugar e dar-lhe as permissões corretas ...
Jens Timmerman
@JensTimmerman Você precisa de acesso root para dar as permissões corretas. Se você pode apenas renomeá-lo ou vinculá-lo. Não há necessidade de fazer o download. Se você instalar o SUID em um ID de usuário de destino (se funcionar dessa maneira), você já deverá ter comprometido o ID de usuário de destino.
BillThor
ah, certo, ele se recusa a trabalhar sem setuid, meu mau ...
Jens Timmerman
2

Você pode comparar o ID do usuário efetivo versus o real.

Isso não significa estritamente que está sendo executado desfazer o sudo (também pode ser configurado), mas indica que o programa tem mais direitos do que o usuário pode esperar. (por exemplo, em um programa que normalmente é executado sem esses direitos, mas precisa ser executado com eles durante a instalação ou para instalar atualizações. Em seguida, você pode usá-lo para fornecer um aviso sobre isso).

blabla999
fonte
2
Não, sudodefine o ID efetivo e o real. Ao contrário de suid, o que não acontece. Aqui está um programa C trivial que você pode usar para testar (desculpe, o comentário removerá as novas linhas, você precisará adicioná-las novamente):#include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { printf("real = %i, effective = %i\n", getuid(), geteuid()); return 0; }
derobert
... ou, alternativamente,perl -E 'say $<, "\n", $>'
derobert 27/01
2

Você pode verificar a variável UID (EUID) efetiva, da seguinte maneira:

if [[ $EUID -eq 0 ]]; then
    echo "running as root"
else
    echo "not running as root"
fi
Eliran Malka
fonte
Isso não responde à pergunta. O código fornece a mesma saída quando executado como root e quando executado como sudo.
Stephen C
@ StephenC - eu acho que, para os propósitos do OP, não há diferença. IMHO, seu objetivo é identificar a execução do sudo ou a partir de um shell raiz autêntico, sem distinção.
Eliran Malka
11
Eu acho que você pode estar certo. Eu vim aqui porque não entendi por que sudo echo $USERimprime o nome de usuário não privilegiado (a variável é substituída ANTES do sudo). Acabei usando seu código no meu script. Obrigado!
Stephen C
muito bem-vindos :)
Eliran Malka
-1

Você pode tocar em um arquivo /roote depois if -enele. E se -e for verdadeiro rm(verificando o código de erro) para que seu teste funcione na próxima vez.

A verificação do código de erro (ou código de retorno) após a rm impede que alguém use com facilidade os poderes do sudo para criar o arquivo para fazer uma brincadeira com você.

Chris K
fonte
4
Esta resposta verifica se o processo tem permissão para gravar /root(o que não é necessariamente o mesmo que o UID 0), mas não verifica se obteve essas permissões usando sudo.
Ladadadada
Sim, as "mil maneiras de esfolar um gato"; enquanto escrevia a resposta, pensei em outras 4 ou 5 coisas, então envolvi-a.
Chris K
-2

Descobri que isso funciona bem para isso

[ $(cat /proc/$PPID/loginuid) -ne 0 ] && [ "$USER" == "root" ]
ruckc
fonte
Isso não funciona quando eu tento no FreeBSD, Centos7 ou MacOS X. Acho que você quer dizer "/ proc" em vez de "/ etc". Mas mesmo com essa mudança, ele não funciona em nenhum desses três. "$ USER" é redefinido pelo sudo. Você quis dizer $ SUDO_USER? Além disso, você quis dizer "[[" em vez de "["?
TomOnTime
11
eu consertei o exemplo. basicamente, a verificação do loginuid não é igual a 0, mas o usuário é root.
ruckc