Como impedir que um script seja executado se não for root (e ecoar “Não executando como root! Saindo…”)

16

Aqui está minha fonte:

#!/bin/bash

echo "Running script to free general cached memory!"
echo "";
echo "Script must be run as root!";
echo "";
echo "Clearing swap!";
swapoff -a && swapon -a;
echo "";
echo "Clear inodes and page file!";
echo 1 > /proc/sys/vm/drop_caches;
echo "";

Ele limpa caches e coisas, e ecoa que ele precisa ser executado como root no terminal. Eu basicamente só quero que o script pare de funcionar se detectar que não está sendo executado como root.

Exemplo:

"Running script to free general cached memory!"
"Warning: script must be run as root or with elevated privileges!"
"Error: script not running as root or with sudo! Exiting..."

Se for executado com privilégios elevados, ele é executado normalmente. Alguma ideia? Obrigado!

    
por M. Knepper 31.08.2017 / 03:42

4 respostas

46
#!/bin/sh

if [ "$(id -u)" -ne 0 ]; then
        echo 'This script must be run by root' >&2
        exit 1
fi

cat <<HEADER
Host:          $(hostname)
Time at start: $(date)

Running cache maintenance...
HEADER

swapoff -a && swapon -a
echo 1 >/proc/sys/vm/drop_caches

cat <<FOOTER
Cache maintenance done.
Time at end:   $(date)
FOOTER

O usuário root tem UID 0 (independentemente do nome da conta "root"). Se o UID efetivo retornado por id -u não for zero, o usuário não executará o script com privilégios de root. Use id -ru para testar o ID real (o UID do usuário invocando o script).

Não use $EUID no script, pois isso pode ser modificado por um usuário não privilegiado:

$ bash -c 'echo $EUID'
1000

$ EUID=0 bash -c 'echo $EUID'
0

Se um usuário fizesse isso, obviamente não levaria ao escalonamento de privilégios, mas poderia levar a que os comandos do script não pudessem fazer o que eles deveriam fazer e os arquivos sendo criados com o proprietário errado, etc.

    
por 31.08.2017 / 07:56
19

Acho que o que você quer é verificar se você tem privilégios de superusuário, ou seja, se o seu ID de usuário efetivo é 0.

zsh e bash disponibilizam isso na variável $EUID , assim você pode fazer:

if ((EUID != 0)); then
  echo >&2 "Error: script not running as root or with sudo! Exiting..."
  exit 1
fi

Com quaisquer shells parecidos com POSIX, você pode usar o comando id standard:

if [ "$(id -u)" -ne 0 ]; then
  echo >&2 "Error: script not running as root or with sudo! Exiting..."
  exit 1
fi

Observe que todas as variáveis id -un ou whoami ou $USERNAME em zsh fornecerão o nome de usuário primeiro para o uid. Em sistemas que possuem outros usuários com ID 0, isso pode não ser root , mesmo que o processo seja descendente de um que tenha sido autenticado como root .

$USER normalmente dá a você o usuário autenticado, mas confiar nele é bastante frágil. Ele não é definido pelo shell, mas geralmente é definido pelo comando de autenticação (como login , su (em sistemas GNU / Linux, não necessariamente outros), sudo , sshd (aquele do openssh pelo menos ) ...). Não é sempre assim (mudar o uid não automagicamente definir essa variável, tem que ser feito explicitamente pelo aplicativo alterando o uid) e também poderia ter sido modificado por algum outro processo na linhagem do shell. $LOGNAME , com a mesma advertência é mais confiável, conforme especificado pelo POSIX (originalmente do FIPS 151-2)

    
por 31.08.2017 / 08:06
12

Você pode usar $USER ou whoami para verificar o usuário atual.

if [[ "$USER" != "root" ]]; then
    echo "Error: script not running as root or with sudo! Exiting..."
    exit 1
fi

if [[ $(whoami) != "root" ]]; then
    echo "Warning: script must be run as root or with elevated privileges!"
    exit 1
fi

if [[ $(id -u) != "0" ]]; then
    echo "Error: script not running as root or with sudo! Exiting..."
    exit 1
fi
    
por 31.08.2017 / 03:45
10

O que você realmente quer determinar é se você tem acesso a essas operações. É considerado uma má prática checar se você está ou não no lugar.

Se o sistema tiver sido configurado para permitir que um usuário não-root modifique o cache de páginas de troca e descarte, por que esse usuário não deveria executar seu script?

Em vez disso, você pode simplesmente tentar a operação e sair com uma mensagem útil se ela falhar:

if ! ( swapoff -a && swapon -a )
then
  echo "Failed to clear swap (rerun as root?)" >&2
  exit 1
fi

if ! echo 1 > /proc/sys/vm/drop_caches
then 
  echo "Failed to free page cache (rerun as root?)" >&2
  exit 1
fi
    
por 31.08.2017 / 22:06