Solicitar privilegios de root desde un script

23

Tengo un script que puede ejecutarse como sudo script.shopkexec script.sh

Sería mucho mejor desde el punto de vista del usuario si el script solicitara la contraseña del usuario cuando solo la ejecutara por su nombre script.sh.

¿Cómo puedo "incrustar" la solicitud pkexeco sudoejecutar el script completo con privilegio de root?

Tenga en cuenta que ejecutar todo con sudo sh -cpodría no ser la mejor solución ya que tengo funciones en el script.

Sergiy Kolodyazhnyy
fuente

Respuestas:

55

Esto funcionará:

echo "$(whoami)"

[ "$UID" -eq 0 ] || exec sudo "$0" "$@"

ejemplo:

./test.sh 
blade
[sudo] password for blade: 
root
cuchilla19899
fuente
3
Lo bueno de esto es la recursividad exec: llámese a sí mismo pero al mismo tiempo reemplace el proceso, para que no generemos múltiples instancias del script
Sergiy Kolodyazhnyy
1
Recursion al rescate !!! ¡Recuérdame agregar una recompensa a esta en unos días!
Fabby
66
Algo a tener en cuenta al hacer esto es la escalada de privilegios; Básicamente, cuantos más comandos ejecute como root, más oportunidades hay para que un hacker malintencionado explote algo para obtener acceso a una cuenta root. No digo que siempre sea incorrecto hacer que todo el script se ejecute como root, pero vale la pena pensarlo un poco antes de decidir hacerlo. Creo que sería bueno (aunque no necesario) si la respuesta tocara eso.
David Z
Si tiene un valor de tiempo de espera decente establecido en / etc / sudoers, entonces opcionalmente puede colocar sudo delante de cada comando en el script que realmente necesita acceso de root y solo lo pedirá una vez. Una cosa que a menudo me equivoco es que llamar a un script de este tipo desde una interfaz gráfica de usuario no funcionará porque sudo obtiene / dev / null para la entrada de contraseña y falla. Para eso se diseñaron gksudo y kdesudo, ya que usarán la interfaz gráfica de usuario para solicitar la contraseña.
Joe
1
@ Coder256: No creo que tu edición haya sido correcta. "$@"se expandirá a varias palabras, una para cada parámetro.
jwodder
12

Si desea un bonito diálogo, intente algo como esto. Extraje esto directamente de otra cosa que escribí, por lo que tiene cosas adicionales que quizás no necesite o desee, pero muestra la idea general:

brand="My Software"

# Check that the script is running as root. If not, then prompt for the sudo
# password and re-execute this script with sudo.
if [ "$(id -nu)" != "root" ]; then
    sudo -k
    pass=$(whiptail --backtitle "$brand Installer" --title "Authentication required" --passwordbox "Installing $brand requires administrative privilege. Please authenticate to begin the installation.\n\n[sudo] Password for user $USER:" 12 50 3>&2 2>&1 1>&3-)
    exec sudo -S -p '' "$0" "$@" <<< "$pass"
    exit 1
fi

diálogo sudo

Esto usa whiptail, que puede instalar si aún no lo tiene:

sudo apt-get install whiptail
Michael Hampton
fuente
1
¿Por qué guarda la contraseña en una variable?
heemayl
10
¡No llames exec echo [PASSWORD]! Generará un proceso con la contraseña en la línea de comandos que cualquier usuario puede ver. Utilice el comando incorporado echo(forzar la versión incorporada con builtin echo) o el bashism <<<(así :) sudo ... <<< "$pass"; Sh y otros proyectiles tienen Documentos Aquí para estos casos. Además, indique la contraseña en caso de que contenga caracteres especiales.
David Foerster
También puede poner el whiptailcomando en una secuencia de comandos y el uso separado algo así como SUDO_ASKPASS=/path/to/askpass-with-whiptail.sh sudo -A -p "My password prompt" -- "$0" "$@"tener sudotrato con la contraseña de mensajes personalizados.
David Foerster
@DavidFoerster Eso podría funcionar, pero luego necesita dos scripts, o escribe su script askpass en un archivo temporal y luego lo pasa a sudo.
Michael Hampton
Ok, sin embargo, otros ya notaron que no es deseable pasar la contraseña a una variable. La forma en que la id se aproxima a esto es pasar la salida del diálogo a la tubería con nombre como he mostrado aquí askubuntu.com/a/704643/295286
Sergiy Kolodyazhnyy
11

La respuesta de blade19899 es de hecho el camino a seguir, sin embargo, también se podría llamar sudo bashal shebang:

#!/usr/bin/sudo bash
# ...

La advertencia obvia es que esto solo funcionará mientras se invoque el script ./scripty fallará tan pronto como se invoque el script bash script.

kos
fuente
55
Esta es una de las razones por las que nunca debe escribir bash scripten la línea de comando para invocar un script. Si el script especifica algo diferente a bashla #!línea, entonces invocarlo con bash scriptva a fallar. Si intentara invocar un script de Python usando bash script.py, también fallaría.
kasperd
1
Sin embargo perl script, puedes ejecutarlo con . Perl, en un esfuerzo por ser realmente agradable, verifica la línea shebang, y si no está invocando a Perl, ejecuta el programa correcto.
tbodt
Esto es malo porque ejecuta todos los comandos en el script con sudo. Es mejor aislar los pocos comandos que realmente necesitan sudo y agregarlos cuando sea necesario. No incluya la evaluación de funciones en estas llamadas sudo; deberían ser lo más claros y mínimos posible.
Douglas celebrada el
@DouglasHeld Si bien estoy de acuerdo con eso, esto es lo que la pregunta me pide: "¿Cómo puedo" incrustar "la solicitud a pkexec o sudo para ejecutar todo el script con privilegio de root?". Estoy bastante seguro de que habría casos de uso en los que sería útil poder hacer esto.
kos
6

Prefacio los comandos dentro de la secuencia de comandos que necesitan acceso raíz con sudo: si el usuario aún no ha obtenido permisos, la secuencia de comandos solicita una contraseña en ese punto.

ejemplo

#!/bin/sh 
mem=$(free  | awk '/Mem:/ {print $4}')
swap=$(free | awk '/Swap:/ {print $3}')

if [ $mem -lt $swap ]; then
    echo "ERROR: not enough RAM to write swap back, nothing done" >&2
    exit 1
fi

sudo swapoff -a && 
sudo swapon -a

Este script puede ejecutarse como sudo <scriptname>o como <scriptname>. En cualquier caso, le pedirá la contraseña, solo una vez.

Charles Green
fuente
2
El problema aquí es que puede haber múltiples comandos que necesitan acceso a la raíz, lo que significa llamar sudoa 25 comandos diferentes de forma redundante; es más fácil llamar a sudo una vez. Aquí, sin embargo, la razón por la que su script llama a sudo solo una vez es porque sudo tiene un tiempo de espera de 15 minutos; los comandos que tardan más de ese tiempo deberán volverse a adoptar. Tu camino funciona justo. . . no como lo necesito para funcionar.
Sergiy Kolodyazhnyy
@Serg Para un pequeño script, la forma en que lo hice fue rápida y fácil: ¡realmente no soy un programador elegante!
Charles Green
Eres el mejor programador que publica en esta página. Está utilizando sudo exactamente como debería usarse, solo donde sea necesario y con resultados muy claros esperados.
Douglas se celebró el
4

Parece que nadie más ha abordado la preocupación obvia aquí. Poner sudodentro de su script que luego distribuye promueve malos hábitos de usuario . (Supongo que lo está distribuyendo porque menciona "desde el punto de vista del usuario").

La verdad es que hay una directriz en el uso de aplicaciones y scripts que es similar al principio de seguridad en la banca de: Nunca dé su información personal a alguien que lo llame y diga que está llamando "desde su banco" , y que existe por razones similares

La regla para las aplicaciones es:

Nunca escriba su contraseña cuando se le solicite, a menos que esté seguro de lo que se está haciendo con ella. Esto se aplica por triplicado a cualquier persona con sudoacceso.

Si está escribiendo su contraseña porque se ejecutó sudoen la línea de comando, genial. Si lo está escribiendo porque ejecutó un comando SSH, está bien. Si lo está escribiendo cuando inicia sesión en su computadora, genial, por supuesto.

Si solo ejecuta un script o ejecutable extranjero e ingresa su contraseña cuando se le solicite, no tiene idea de lo que el script está haciendo con él. Podría estar almacenándolo en un archivo temporal en texto plano, por lo que sabes, e incluso podría fallar al limpiarlo.

Obviamente, hay preocupaciones separadas y adicionales sobre la ejecución de un conjunto desconocido de comandos como root, pero de lo que estoy hablando aquí es de mantener la seguridad en la contraseña . Incluso suponiendo que la aplicación / script no sea malicioso, aún desea que su contraseña se maneje de manera segura para evitar que otras aplicaciones la consigan y la usen maliciosamente.

Entonces, mi propia respuesta personal a esto es que lo mejor que puede incluir en su script si necesita privilegios de root es:

#!/bin/bash
[ "$UID" -eq 0 ] || { echo "This script must be run as root."; exit 1;}

# do privileged stuff, etc.
Comodín
fuente
Si bien estoy completamente de acuerdo con usted, un usuario que ejecuta algo sin saber qué hace, ya que sudo script_namees igual de vulnerable, es lo mismo. Tal vez esta idea promueva malos hábitos, no diré nada al respecto. Pero la clave es saber lo que hace un programa, y ​​eso es responsabilidad del usuario. Esa es toda la idea detrás del software de código abierto. En cuanto a mi propio guión, bueno. . . un script es texto sin formato: los usuarios pueden leerlo si quieren saber lo que hace
Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy es similar, pero si escribe su contraseña directamente en el script, en realidad es peor. Un script ejecutado con sudo todavía no conoce su contraseña.
Comodín
1

Lo hice de esta manera:

echo -n "Enter password for sudo rights: "
read -s pass

echo $pass | sudo -S [your command here]
88 pesado
fuente
44
Al menos cita tus variables.
Muru
Y es posible que citar sus variables ni siquiera ayude si su contraseña comienza con un guión.
Comodín