¿Puede un programa decir que se está ejecutando bajo sudo?

27

Tengo un programa que debería comportarse de manera diferente si se ejecuta bajo "sudo". ¿Hay alguna manera de saber si se ejecutó bajo sudo?

Actualización: Alguien preguntó por qué querría hacer esto. En este caso, en una Mac que usa MacPorts, hay una salida que le indica que corte y pegue un comando en particular. Si el comando MacPorts se ejecutó con "sudo", debe incluir sudo en el comando de muestra:

$ 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
fuente
Tengo curiosidad: ¿puedes explicar cómo debería comportarse de manera diferente?
Sciurus
1
@sciurus generalmente el caso de uso común está en un script de instalación que requiere privilegios de root; si no los tienes, simplemente muere de inmediato.
Nick T
3
Esto suena como meta.stackexchange.com/questions/66377/what-is-the-xy-problem/… . ¿Qué es lo que realmente quieres hacer?
Jenny D dice Reinstate Monica
Recuerdo vagamente que algún comando es consciente de que se ejecuta como root o no ... Creo que la respuesta es "sí"
Rolf

Respuestas:

48

Sí, hay 4 variables de entorno establecidas cuando un programa se ejecuta en sudo:

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

Tenga en cuenta que estos pueden ser falsificados simplemente configurándolos. No confíes en ellos para nada crítico.

Por ejemplo: en este programa necesitamos decirle al usuario que ejecute algún otro programa. Si el actual se ejecutó con sudo, el otro también lo 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

Tenga en cuenta que solo prueba una variable SUDO_ * si primero puede probar que se está ejecutando como root. Incluso entonces solo lo usa para cambiar algún texto útil.

TomOnTime
fuente
2
¿Qué usaría para "algo crítico"?
Kevin - Restablece a Mónica el
3
@Kevin si alguien se mete con su entorno para fingir que tiene privilegios elevados, entonces con suerte sabrá lo que está haciendo y aceptará las consecuencias.
Nick T
Votados en contra porque cualquier respuesta que tenga que calificarse como "no confíes en ellos para nada crítico" no es una respuesta en absoluto, sino un truco feo.
Stephen C
Esta es una respuesta perfectamente aceptable a la pregunta que se hizo. La advertencia debe estar presente para las personas que podrían tratar de evitar el uso de sudo, en lugar de solo detectarlo . La prevención debe hacerse utilizando los alias de comando de sudo para limitar qué comandos puede ejecutar el usuario.
dwurf
11

Esto no responde la pregunta directamente, pero no creo que se haga la pregunta correcta aquí. Me parece que el autor de la pregunta quiere un programa que presumiblemente actuará de manera diferente si tiene ciertos permisos o no, sin embargo, diría que buscar sudo no es la forma de hacerlo. En primer lugar, muchos sistemas pueden no implementar un "sudo", de ninguna manera se requiere en Linux o en muchos Unix.

Por ejemplo, un usuario puede haber iniciado sesión como root ya, lo que hace que el sudo sea absurdo o tal vez el sistema tenga usuarios no root que aún tengan capacidades para realizar la tarea administrativa que el programa desee realizar. Finalmente, tal vez el sistema no tiene root o sudo en absoluto y en su lugar utiliza un sistema de control de acceso obligatorio con diferentes capacidades y no atrapa a todos los superusuarios en los que sudo. O el usuario podría suudirse, pero en una cuenta que tiene permisos sin su propia cuenta por razones de seguridad (a menudo ejecuto código no confiable con un usuario temporal sin privilegios que solo puede escribir en ramdisks para cancelar, no aumentar mis permisos ) En general, es una mala idea asumir un modelo de permisos específico como sudo o la existencia de root o asumir que un usuario sudoed tiene privilegios particulares.

Si desea averiguar si tiene permisos para realizar una operación, la mejor manera es simplemente intentarlo y luego verificar si no hay problemas de permisos si falla o si se trata de una operación de varias etapas que debe fallar o tener éxito. puede verificar si una operación funcionará con funciones como la función de acceso POSIX (tenga cuidado con las posibles condiciones de carrera aquí si los permisos se cambian activamente)

Si además necesita conocer al usuario real detrás del sudo, puede usar la función getlogin que debería funcionar para cualquier sesión interactiva con un terminal subyacente y le permitiría, por ejemplo, encontrar quién está 'realmente' ejecutando el comando para auditar o encontrar el directorio de inicio del usuario real para guardar registros.

Finalmente, si lo que realmente quiere es averiguar si un usuario tiene acceso de root (sigue siendo una mala idea pero menos específica de implementación) puede usar getuid para verificar un uid de 0 y, por lo tanto, root.

La realidad
fuente
7

Hay dos mecanismos que se pueden usar.

  • La verificación de las variables de entorno se puede falsificar de cualquier manera, pero es la más fácil de hacer. growisofsno le gusta correr bajo SUDO, así que desarmado las variables SUDO en los scripts donde lo uso. Se puede falsificar a la inversa. (Las variables SUDO también se llevan al entorno para los scripts que se ejecutan bajo los comandos at y batch).
  • Otra forma de ver si se está ejecutando en sudo es recorrer la lista de procesos desde su proceso principal buscando sudo. Sería difícil ocultar que estabas corriendo bajo sudo de esta manera, pero es más complejo. Todavía es posible fingir que estás ejecutando bajo sudo.

Es más común verificar si se está ejecutando como el usuario apropiado. El idcomando se puede usar para hacer esto. El script de TomOnTime usa el idcomando para determinar si sudoes necesario ejecutar el siguiente comando.

BillThor
fuente
1
> Sería difícil ocultar que estabas corriendo bajo sudo de esta manera ¿No podrías simplemente cambiar el nombre del sudobinario a otra cosa? ¿O nombrar algún otro ejecutable sudopara fingir lo contrario? No es que realmente esperara que alguien cuerdo hiciera eso ...
Bob
@Bob Necesitaría rootacceso para cambiar el nombre del sudoejecutable. Un usuario normal no podría hacer esto. Noté que puedes fingir que te estás quedando sin sudo. Cambiar el nombre de un programa existente funcionaría. El código requerido para un sudoprograma falso dedicado es trivial.
BillThor
puedes descargar el binario sudo desde algún lugar y darle los permisos correctos ...
Jens Timmerman
@JensTimmerman Necesita acceso root para otorgarle los permisos correctos. Si solo puede cambiarle el nombre o vincularlo. No es necesario descargarlo. Si lo instala SUID en una identificación de usuario de destino (si funciona de esa manera), ya debe haber comprometido la identificación de usuario de destino.
BillThor
ah, claro, se niega a trabajar sin setuid, mi mal ...
Jens Timmerman
2

Puede comparar la identificación de usuario efectiva versus la real.

Esto no significa estrictamente que se está ejecutando deshacer sudo (también se puede configurar), sino que indica que el programa tiene más derechos de los que el usuario puede esperar. (por ejemplo, en un programa que normalmente se ejecuta sin dichos derechos, pero que debe ejecutarse con ellos durante la instalación o para instalar actualizaciones. Luego, puede usar esto para dar algunos comentarios de advertencia al respecto).

blabla999
fuente
2
No, sudoestablece tanto la identificación efectiva como la real. A diferencia de suid, que no lo hace. Aquí hay un programa trivial en C que puede usar para probar (lo siento, el comentario eliminará las nuevas líneas, tendrá que agregarlas nuevamente):#include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { printf("real = %i, effective = %i\n", getuid(), geteuid()); return 0; }
derobert
... o, alternativamente,perl -E 'say $<, "\n", $>'
Derobert
2

Puede verificar la variable efectiva de UID (EUID), de la siguiente manera:

if [[ $EUID -eq 0 ]]; then
    echo "running as root"
else
    echo "not running as root"
fi
Eliran Malka
fuente
Esto no responde la pregunta. El código da el mismo resultado cuando se ejecuta como root que cuando se ejecuta como sudo.
Stephen C
@StephenC: creo que para los fines del OP, no hay diferencia. En mi humilde opinión, su objetivo es identificar la ejecución de sudo o la ejecución desde un shell raíz auténtico sin distinción.
Eliran Malka
1
Creo que tienes razón. Vine aquí porque no entendía por qué sudo echo $USERimprime el nombre de usuario sin privilegios (la variable se sustituye ANTES del sudo). De hecho, terminé usando tu código en mi script. ¡Gracias!
Stephen C
bienvenido :)
Eliran Malka
-1

Puede tocar un archivo /rooty luego if -e. Y si -e es verdadero rm(verificando el código de error), entonces su prueba funciona la próxima vez.

Verificar el código de error (o el código de retorno) después de que el rm evita que alguien use fácilmente los poderes de sudo para crear el archivo para jugar una broma sobre usted.

Chris K
fuente
44
Esta respuesta verifica si el proceso tiene permiso para escribir /root(que no es necesariamente lo mismo que ejecutar como UID 0), pero no verifica si obtuvo esos permisos usando sudo.
Ladadadada
Sí, las "mil formas de pelar un gato"; Mientras escribía la respuesta, pensé en otras 4 o 5 cosas, así que lo terminé.
Chris K
-2

Descubrí que esto funciona bien para esto

[ $(cat /proc/$PPID/loginuid) -ne 0 ] && [ "$USER" == "root" ]
ruckc
fuente
Esto no funciona cuando lo pruebo en FreeBSD, Centos7 o MacOS X. Creo que te refieres a "/ proc" en lugar de "/ etc". Pero incluso con ese cambio, no funciona en ninguno de esos tres. "$ USER" se restablece por sudo. ¿Quiso decir $ SUDO_USER? Además, ¿quiso decir "[[" en lugar de "["?
TomOnTime
1
Arreglé el ejemplo. básicamente, verificar el loginuid no es igual a 0, pero el usuario es root.
ruckc